Node js not sendin messages to clients - javascript

Hi I am making a simple chat website with node js. I want everyone to see posted messages. The messages are stored in a array and then displayed on the website. The problem is that when a message is posted no one can see it. A user will be able to see it after posting a new message. Can someone help?
const http = require('http');
const { Socket } = require('socket.io');
const WebSocketServer = require('websocket').server;
var steviloSporocil = 0;
let sporocila=[];
const server = http.createServer();
console.log('Server is on port 3000')
server.listen(3000);
const wsServer = new WebSocketServer({
httpServer: server
});
wsServer.on('request', function(request) {
const connection = request.accept(null, request.origin);
connection.on('message', function(message){
sporocila.push(message.utf8Data);
connection.sendUTF(JSON.stringify(sporocila));
console.log('Received Message:', JSON.stringify(sporocila));
});
connection.on('close', function(reasonCode, description) {
console.log('Client has disconnected.');
});
});
<?php ob_start() ?>
<?php
$titel="Chat";
$nekaj=$_SESSION['uporabnik'];
?>
<div class="chat-main" id="text"></div>
<form name='form' method='post' class="form">
<div class="form-group">
<input type="text" class="form-control" id="textbox" name="chat" placeholder="Chat">
<button type="button" class="btn btn-primary" name="gumb" id="gumb" onclick="Poslji()" autocomplete="off">Send</button>
</div>
</form>
<script>
var myInput = document.getElementById("textbox");
var up='<?php echo $nekaj; ?>';
function Poslji(){
if(myInput && myInput.value){
const ws = new WebSocket('ws://localhost:3000');
ws.onopen = function(){
ws.send(up+": "+document.getElementById('textbox').value+"<br>");
};
ws.onmessage = function(e) {
const arr=JSON.parse(e.data);
console.log("Received: '"+e.data+"'");
document.getElementById('text').innerHTML=arr;
};
}
}
</script>
<?php
$content=ob_get_clean();
require "layout.html.php";
?>

Related

Print array in node js server

Hi I have a website from witch I can send a message to node js server and there the message is saved in a a array. When a new message is sent to the server the old message in the array is overwritten by the new message. The array has to contain new and old messages.
The output of console after sending message
const http = require('http');
const { Socket } = require('socket.io');
const WebSocketServer = require('websocket').server;
var steviloSporocil = 0;
const sporocila=[];
const server = http.createServer();
console.log('Server is on port 3000')
server.listen(3000);
const wsServer = new WebSocketServer({
httpServer: server
});
wsServer.on('request', function(request) {
const connection = request.accept(null, request.origin);
connection.on('message', function(message) {
sporocila[steviloSporocil]=[message.utf8Data];
steviloSporocil++;
for (let i = 0; i < steviloSporocil; i++) {
connection.sendUTF(sporocila[i]);
console.log('Received Message:', sporocila[i]);
}
});
connection.on('close', function(reasonCode, description) {
console.log('Client has disconnected.');
});
});
<?php ob_start() ?>
<?php $titel="Chat"; ?>
<div class="chat-main" id="text"></div>
<form name='form' method='post' class="form">
<div class="form-group">
<input type="text" class="form-control" id="textbox" name="chat" placeholder="Chat">
<button type="button" class="btn btn-primary" name="gumb" id="gumb" onclick="Poslji()" autocomplete="off">Send</button>
</div>
</form>
<script>
function Poslji(){
const ws = new WebSocket('ws://localhost:3000');
ws.onopen = function() {
console.log('WebSocket Client Connected');
ws.send(document.getElementById('textbox').value);
};
ws.onmessage = function(e) {
console.log("Received: '" + e.data + "'");
document.getElementById('text').innerHTML=e.data;
};
}
</script>
<?php
$content=ob_get_clean();
require "layout.html.php";
?>
If I understood everything, here how to solve your problem:
you take all previous message at the specified index and add the new one at the end. If you want to add it at the top, then just invert the two lines.
sporocila[steviloSporocil] = [
...sporocila[steviloSporocil],
message.utf8Data
];
You are sending the messages in the array to the client separately using a for-loop and connection.sendUTF(sporocila[i]); and then displaying the last message received using document.getElementById('text').innerHTML=e.data;.
Are you suprised then that your website only shows the last item in the array?
Why not send the entire array using JSON.stringify and then JSON.parse on the client?

How to handle ajax post request with node.js and without framworks?

I'm practicing node js and ajax without any frameworks (like jquery, expressJS) by doing a simple app that gives information about a city's weather using openweatherapi.
Here is my code so far:
app.js
const http = require("http");
const fs = require("fs");
const path = require("path");
const { parse } = require('querystring');
const server = http.createServer((req, res)=>{
if(req.url === "/"){
fs.readFile("index.html", "UTF-8", function(err, data){
res.writeHead(200, {"Content-Type": "text/html"});
res.end(data);
});
}else if(req.url === "/public/styles.css"){
var cssPath = path.join(__dirname + req.url);
var cssFileStream = fs.createReadStream(cssPath, "UTF-8");
res.writeHead(200, {"Content-Type": "text/css"});
cssFileStream.pipe(res);
}else if(req.url === "/public/main.js"){
var jsFileStream = fs.createReadStream(`${__dirname}/${req.url}`, "UTF-8");
res.writeHead(200, {"Content-Type": "text/js"});
jsFileStream.pipe(res);
}else if(req.url === "/favicon.ico"){
res.statusCode=204;
res.end();
};
if(req.url ==="/"&&req.method==="POST"){
let body = "";
req.on('data', chunk=>{
body += chunk.toString();
});
req.on("end", ()=>{
parse(body);
});
console.log(body);
};
});
var PORT = process.env.port || 3000;
server.listen(PORT);
console.log(`Server listening on port ${PORT}`);
index.html
<!DOCTYPE html>
<html>
<head>
<title>Weather Application</title>
<link href="./public/styles.css" rel="stylesheet" type="text/css"/>
<script src="./public/main.js"></script>
</head>
<body>
<div class="weather-div">
<h1> Search for weather information of a city</h1>
<form method="post" action="/">
<input class="locationName" id="cityName" name="city" type="text" placeholder="City" required/>
<input class="locationName" id="countryName" name="city" type="text" placeholder="Country"/>
</form>
<button id="submitBtn" type="submit">Search Weather</button>
</div>
<body>
</html>
main.js
function getData(){
var city = document.getElementById('cityName');
var country = document.getElementById('countryName');
if(city.value.length>0){
const apiKey = "APIKey";
const apiUrl = "http://api.openweathermap.org";
const xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
};
};
xhttp.open("POST", "app.js",true);
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.send(`city=${city}&country=${country}`);
};
};
window.onload=function(){
document.getElementById("submitBtn").addEventListener("click", getData, false);
};
So what i want to do is to send the city name of the input using ajax because i tried with a simple form and a submit button, but it keeps on refreshing the page. I don't want it. And I want a receive the data in app.js to parse it and filter its code with a json file of cities and then return it to main.js to send an api call to openweathermap.
Fortunately i know how to do the simple stuff: the parsing and the api call. But all the other stuff i have totally no idea. when i search about it, I only find a solution using jquery or express, but I don't want that, i want pure javascript to get better.
Thank you in advance.
First argument in an event callback is the event object. For a form, to prevent the default browser behavior of refreshing or navigating to the action page, use e.preventDefault().
So the click event that executes callback getData would look like:
function getData(e){ // First argument of an event callback is the event
e.preventDefault(); // Prevent default button type submit behavior
var city = document.getElementById('cityName');
var country = document.getElementById('countryName');
if(city.value.length>0){
const apiKey = "APIKey";
const apiUrl = "http://api.openweathermap.org";
const xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
};
};
xhttp.open("POST", "app.js",true);
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.send(`city=${city}&country=${country}`);
};
};

I need the route data in a node client between client to correct connected user

I am trying to build a gnuchess web api and bind it to a graphical web interface. Trought a websocket the users will connect and when connecting the server-websocket will launch a "gnuchess" as subprocess. Then I would like to communicate with the gnuchess's stdin/stdout and send the stream to the user. But as the code is today it only starts new gnuchess's but I could only write to one of them (with all connected clients I could do that)
I have this code node-code:
var http = require("http");
var ws = require("./");
var fs = require("fs");
var process = require('child_process');
theglobal = "";
var ls = "";
// Web server
http.createServer(function (req, res) {
fs.createReadStream("index.html").pipe(res)
}).listen(8080);
// Socket stuff
var server = ws.createServer(function (connection) {
connection.on("text", function (str) {
var tmp_cmd = str.split(" ")[0];
var tmp_string = str.substr(str.indexOf(" ") + 1);
console.log(tmp_cmd)
console.log(tmp_string)
if (tmp_cmd == "move") {
ls.stdin.write(tmp_string + "\n");
connection.sendText(str);
}
if (str == "start") {
connection.sendText(str);
ls = process.spawn('/usr/games/gnuchess');
ls.stdout.on('data', function (chunk) {
broadcast(chunk)
});
}
})
});
server.listen(8081);
// Functions
// This broadcasts to all clients connected
function broadcast(str) {
server.connections.forEach(function (connection) {
connection.sendText(str)
})
}
HTML:
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Chat example</title>
<script>
var connection
window.addEventListener("load", function () {
var nickname = prompt("Choose a nickname")
if (nickname) {
connection = new WebSocket("ws://"+window.location.hostname+":8081")
connection.onopen = function () {
console.log("Connection opened")
connection.send(nickname)
document.getElementById("form").onsubmit = function (event) {
var msg = document.getElementById("msg")
if (msg.value)
connection.send(msg.value)
msg.value = ""
event.preventDefault()
}
}
connection.onclose = function () {
console.log("Connection closed")
}
connection.onerror = function () {
console.error("Connection error")
}
connection.onmessage = function (event) {
var div = document.createElement("div")
div.textContent = event.data
document.body.appendChild(div)
}
}
})
</script>
</head>
<body>
<form id="form">
Message: <input size="50" id="msg"> <input type="submit" value="Submit">
</form>
</body>
</html>
But what happens is that it starts a new gnuchess for every user who connects (it should be like that) but the data routes to the first openeded gnuchess.
Could solve the problem by using a IRC bot and IRC server and use different channel for each game (#gnuchess_user1, #gnuchess_user2, etc..) But I think it's easier actually to solve it by making a method or own object for each user and route it in the websocket.
You should look at socket.io, it has built in support for rooms:
io.on('connection', function(socket){
socket.join('some room');
});
Which means you can broadcast to all sockets connected to that room. You don't have to spawn separate processes for these (it will be devastating for your performance..)
io.to('some room').emit('some event');
http://socket.io

How to save Data in MongoDB from forms

I have a form. I need to get text from my form to save it in MongoDB.
tweets.ejs:
<form method="post" action="/tweets">
<input type="text" id="txt" name="text"/>
<input type="button" id="btn" value="Touch me">
</form>
Here is my route file tweets.js:
var Message = require('models/messages');
exports.get = function(req,res) {
res.render('tweets')
};
I use mongoose schema(models/messages.js):
var mongoose = require('../libs/mongoose'),
Schema = mongoose.Schema;
var MessageSchema = new Schema({
message: String,
date: Date
});
var Message = mongoose.model('Message', MessageSchema);
module.exports = Message;
I tried set var m = req.body.text in tweets.js, but I think it's absolutely wrong way
exports.post = function(req,res){
var m = new Message;
m.message = req.body.text;
m.save(); }
Explain me how to do it right please!
in your routes or app file route should be
var tweets = require("tweets");
app.post("/tweets", tweets.post);
in your tweets.js file
var Message = require('models/messages');
exports.post = function(req,res){
console.log(req.body.text)
var msg = {message:req.body.text,date:new Date()};
Message(msg).save(function(error,data){
if (data){
console.log("Save "+ JSON.stringify(data));
res.send({statud:"OK",msg:data})
}
else{
res.send({statud:"Cancel"})
}
});
}

AJAX to PHP not sending data to database using NODEJS

I'm currently developing a chat project.. I'm using a php framework and have managed to run it on node now the problem I'm currently experiencing is that the ajax query is not working it does not send a single data to my database.. the script that I used is perfectly working because I used this script when I was still using a long-polling of ajax for a chat app... It just didnt work now when I used it on the new chat app using node that I was developing... Here is my index.php
<?php startblock('script') ?>
<script src="/socket.io/socket.io.js"></script>
<script src="http://code.jquery.com/jquery-1.11.1.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){
var data2 = { text: msg };
$.ajax({
url: 'localhost:3000/includes/message/store_chat.php',
dataType: 'json',
type: 'POST',
data: {json:JSON.stringify(data2)},
success: function (data2) { }
});
});
</script>
<script>
jQuery(function ($) {
$(window).on("resize", function () {
body = $("html,body"),
menu = $("#side-menu").width(),
gridW = body.width() - (menu + 30),
gridH = body.height();
$("#message-app-wrapper").css("height", gridH);
$("#views-wrapper").css("width", gridW);
}).resize();
});
</script>
<?php endblock(); ?>
And this is the database handler
<?php
//Send some headers to keep the user's browser from caching the response.
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT" );
header("Last-Modified: " . gmdate( "D, d M Y H:i:s" ) . "GMT" );
header("Cache-Control: no-cache, must-revalidate" );
header("Pragma: no-cache" );
header("Content-Type: text/plain; charset=utf-8");
$json2 = $_POST['json'];
$data = json_decode($json2);
$text = $data->text;
$con = new PDO("mysql:host=localhost:3000;dbname=schat", "root" , "");
$con->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
$sql2 = "INSERT INTO chat_storage(chat) VALUES(:msg)";
$stmt2 = $con->prepare($sql2);
$stmt2->bindValue( 'msg',$text, PDO::PARAM_STR);
$stmt2->execute();
?>
The index.js is here:
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var validator;
function getStdout(command, args, fn) {
var childProcess = require('child_process').spawn(command, args);
var output = '';
childProcess.stdout.setEncoding('utf8');
childProcess.stdout.on('data', function(data) {
output += data;
});
childProcess.on('close', function() {
fn(output);
});
}
app.use('/assets', require('express').static(__dirname + '/assets'));
app.use('/temp', require('express').static(__dirname + '/temp'));
app.use('/includes/message', require('express').static(__dirname + '/includes/message'));
app.get('/', function(req, res) {
//res.sendfile(__dirname + '/' +validator);
res.send(validator);
});
//you should have only one io.on('connection')
io.on('connection', function(socket) {
socket.on('chat message', function(msg){
console.log('message: ' + msg);
io.emit('chat message', msg);
});
});
getStdout('php', ['index.php'], function(output) {
validator = output;
//start your server after you get an output
http.listen(3000, function() {
console.log(validator);
});
});
These are what I have so far. For some reason it wont' store to my database I don't know if I did something wrong here or have missed to add something.
Try talking directly to mysql within node.js. Also good to create a new username instead of logging as root to mysql. Here's a code snippet, with some comments:-
var mysql = require('mysql'); // run: npm install mysql
var http = require('http');
var express = require('express');
var app = express();
var connection = mysql.createConnection({ // setup the connection
host : "localhost",
user : "username",
password: "password",
})
connection.connect(function(err) { // connect and handle errors
if(err) {
// handle your errors here
}
}); // end .connect()
app.get('/path/:msg', function(req,res){ // process incoming message
res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' })
var myMsg= req.params.msg; // obtain the incoming msg
var strQuery = "INSERT INTO chat_storage(chat) VALUES(?)"; // your SQL string
connection.query("use schat"); // select the db
connection.query( strQuery, myMsg, function(err, rows){
if(err) {
// handle errors
} else {
// message received
}
}); end .query()
}); // end app.get()

Categories