I'm learning node.js and i want to write a program that draws a graph of data fetched from mysql database. I am doing the back end processing in the server.js file and showing results in index.html. Since i'm new to node.js and web programming. I don't know how to get data as a javascript object and draw it's graph.
Question:
I want to know how would i send the data fetched into the javascript object to the graph drawing code.
Here is my server.js :
var mysql = require('mysql');
var express = require('express');
var app =express();
var country = [], population = [], gdp = [];
var jsonArray;
var connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '12345',
database: 'rohan'
});
var queryString = 'SELECT * FROM Country';
// Fetching data from database
app.get('/', function(req, res) {
connection.query(queryString, function(err, rows, fields) {
if(err) throw err;
formatData(rows);
res.send(jsonArray);
console.log(jsonArray);
});
});
function formatData(dataArray) {
for(var i = 0; i < dataArray.length; i++) {
country[i] = dataArray[i].name;
population[i] = dataArray[i].population;
gdp[i] = dataArray[i].GDP;
}
jsonArray = [country, population, gdp];
console.log("in FormatData()...\n");
console.log(jsonArray);
}
app.listen(3000, function() {
console.log("Server listening on port 3000");
});
and this is my index.html:
<html>
<head>
<title>Chart-mysql demo</title>
<script>
// code to draw graph
$("#clients").bind('ajax:success', function(result) {
console.log("In index.html" + result);
alert(result);
var barData = {
label:result.country,
datasets: [
{
label: '2010 Customers #',
fillColor: '#382765',
populationData:result.population
}
]
};
var context = document.getElementById('clients').getContext('2d');
var clientsChart = new Chart(context).Bar(barData);
});
</script>
</head>
<body>
<h1>Country Demographics</h1>
<script src="Chart.js"></script>
<script src="app.js"></script>
<canvas id="clients" width=500 height=400></canvas>
</body>
</html>
As I see you haven't get data from node.js app. First of all you need to somehow retrieve this html from server, so you need to add something like:
app.get('/', function(req, res) {
res.render('index.html');
});
Then you need to change your current app.get('/' to some another url. Let's say "/data".
After that change you need to change your current index.html, and add there JS code, which will request data from "/data". You can use jquery for that. Take a look at http://api.jquery.com/jquery.ajax/ Then you will get an JS object in callback of Jquery ajax request to node.js "/data".
You should first write a module which would fetch the data(you have got a piece of code which connects to the database so we can skip this part).
Then we should write a router which would pass the data to the pathname (when it is called) for example like this:
router.get('/', function(req, res, next) {
api.apiGet(function (data){
-> importing data from module (api is a variable importing the module, apiGet a function from api).
res.render('portal', {result: data}); -> data is passed as result
});
});
Then you would write a view which would use that data, for example in Jade it would be the following.
{val[4].label}
It just grabs the data which is send in JSON.
If you need something clearing just write :)
After hours of head scratching i finally did it.As far as server side was concerned i was doing it right. I just didn't know how to deal with data on the client. To receive data as a javascript object, I added a button and connected an AJAX call to it's onclick() event.
<body>
<h1>Country Demographics</h1>
<button id="Get_Graph" onclick="gData(); return false">Get Graph<button/>
<canvas id="clients" width=500 height=400></canvas>
</body>
And to handle it's click event, here is javascript code:
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="../Chart.js"></script>
<script>
// code to draw graph
function gData() {
$.get("http://localhost:3000", function(result, status) {
alert(result);
var barData = {
labels:result[0],
datasets: [
{
label: '2010 Customers #',
fillColor: '#382765',
data: result[2]
}
]
};
var context = document.getElementById('clients').getContext('2d');
var clientsChart = new Chart(context).Bar(barData);
});
}
</script>
Related
I'm working on a project where my job is to use Node.js and Socket.io to read a text file (contain 3 real time readings) and got the data in 3 variables, then send them to Socket.io and get them displayed on the website continuously without having to refresh it. I ran my codes, it did not give any errors, but it did not display anything on the website either. So I don't know what is wrong in my code. I need help with passing variables from Node.js to Socket.io and get them displayed on the my web page.
This is my server file:
var http = require('http').createServer(handler); //require http server, and cr$
var fs = require('fs'); //require filesystem module
var io = require('socket.io')(http) //require socket.io module and pass the htt$
http.listen(8080); //listen to port 8080
function handler (req, res) { //create server
fs.readFile(__dirname + '/index.html', function(err, data) { //read file inde$
if (err) {
res.writeHead(404, {'Content-Type': 'text/html'}); //display 404 on error
return res.end("404 Not Found");
}
res.writeHead(200, {'Content-Type': 'text/html'}); //write HTML
res.write(data); //write data from index.html
return res.end();
});
}
io.sockets.on('connection', function (socket) {
setInterval(function(){
var array = fs.readFileSync('report.txt').toString().split("\n");
var volt = (array[0]);
var power = (array[1]);
var temp = (array[2]);
socket.emit('volt',{'volt': volt});
socket.emit('power',{'power': power});
socket.emit('temp',{'temp': temp});
}, 1000);
});
index.html file :
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.3/socket.io.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.js"></script>
<script>
var socket = io('http://10.117.230.219:8080');
socket.on('volt', function (data) {
$('#volt').text(data.volt);
socket.on('power', function (data) {
$('#power').text(data.power);
socket.on('temp', function (data) {
$('#temp').text(data.temp);
});
</script>
<div id="volt"></div>
<div id="power"></div>
<div id="temp"></div>
</body>
You are missing some tags on your HTML page including HTML and head. You are also missing a closing )} for each socket.on(...) call in your script. This is what it should look like:
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.3/socket.io.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.js"></script>
<script>
var socket = io('http://localhost:8080');
socket.on('volt', function (data) {
$('#volt').text(data.volt);
})
socket.on('power', function (data) {
$('#power').text(data.power);
})
socket.on('temp', function (data) {
$('#temp').text(data.temp);
})
</script>
</head>
<body>
<div id="volt"></div>
<div id="power"></div>
<div id="temp"></div>
</body>
</html>
This should do it.
I have just starting learning nodeJS and now I have some trouble understanding how I can style the output from a child_process in html/css.
This far I have the following code:
#!/usr/local/bin/node
var express = require('express');
var app = express();
var fs = require('fs');
var govSh = './../sh/govc.sh';
var util = require('util');
var spawn = require('child_process').spawn;
var PORT = 3333;
if (!fs.existsSync(govSh)) {
console.log("can't find govc script");
process.exit(1);
};
app.get('/vmlist', function(req, res) {
var invPath = spawn(govSh, ['vmlist']);
invPath.stdout.pipe(res);
});
app.listen(PORT, function() {
console.log("app will listen on port 3333");
});
And when I do a reuest to http://127.0.0.1:3333/vmlist I get presented with this in the browser:
{"name":"centos1", "state":"poweredOff", "ram":"1", "vcpu":"1", "ip4":""}
{"name":"centos2", "state":"poweredOff", "ram":"8", "vcpu":"2", "ip4":""}
How is it possible for me to use this in html and style it with css? Or how can I send it to a client side jQuery / Ajax?
EDIT:
As it looks now, the govc.sh script will output like above. But this is not a requirement for me, i just want to use the output in html and style it. In the govc.sh script it's with printf i output the info with a for loop:
printf '{"name":"%s", "state":"%s", "ram":"%s", "vcpu":"%s", "ip4":"%s"}\n' ${name} ${vmState} ${vmRam} ${vmCpu} ${vmIp4}
I can change this if it makes things easier in nodejs/javasript.
To render as normal page You've to use ejs, jade templating or output html file (like in this example) and then call api from outputted html using jquery or etc.
Server-side code example
var express = require('express');
var app = express();
var fs = require('fs');
var path = require('path');
var util = require('util');
var execFile = require('child_process').execFile;
var PORT = 3333;
app.use('/assets', express.static('assets')); // create folder "static" relative to this app file and put Your css, js files inside assets
// put index.html file to relative to this file
app.route('/')
.all(function(req, res) {
res.sendFile(path.join(__dirname, 'index.html'));
});
app.route('/vmlist')
.get(function(req, res) {
execFile('./../sh/govc.sh', ['vmlist'], function(err, output) {
if (err) {
return res.status(500).send(err);
}
// I saw in Your question that application returns 2 json objects
// that are an object per line without object delimiter
// and array [] chars that will not well handled,
// so I'm recreating proper json objects array
output = output.split("\n");
var response = [];
for(var o in output) {
var line = output[0].replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, ''); // trimming
if(line != '') {
response.push(JSON.parse(line));
}
}
res.json(response); // responding with application/json headers and json objects in it
});
});
app.listen(PORT, function() {
console.log("app will listen on port 3333");
});
Client-side (index.html):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet" href="/assets/css/common.css">
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<script>
$(function() {
function getVMS() {
$.get('http://127.0.0.1:3333/vmlist', {}, function(vms) {
var html = '';
for(var v in vms) {
var vm = vms[v];
html+= '<div class="cpu">';
html+= 'Name: '+vm.name+'<br/>';
html+= 'State: '+vm.state+'<br/>';
html+= 'RAM: '+vm.ram+'<br/>';
html+= 'IPv4: '+vm.ip4+'<br/>';
html+= '</div>';
}
$('#vmlist').html(html);
});
}
getVMS(); // initially getting VMS
setInterval(getVMS, 10000); // getting VMS continuously every 10 second
});
</script>
</head>
<body>
<div id="vmlist"></div>
</body>
</html>
File structure:
P.S. There may be issue with properly responding from vmlist (because output formatting). if it will not work please execute "govc.sh" from console and give me output of it in comment.
I am trying to create a nodejs app that will search in various web sites using their API. The result will be sent to the client as soon as it receive result from those API using socket.io. The front end will then add those result using jQuery.
What is the best way to implement this?
So Far I have tried:
Sample code 1
At first I created a middleware for express that add the socket to the request like -
var socketMiddleWare = function(req, res, next){
io.on('connection', function(socket){
console.log(io.engine.clientsCount + " clients connected.");
req.socket = socket;
socket.on('disconnect', function(){
console.log(io.engine.clientsCount + " clients after disconnec.");
});
});
next();
};
then added this middleware to my route -
app.use('/users', socketMiddleWare, users);
It works but the problem is it create multiple event listener each time user refresh the page.
Sample code 2
So then I tried (sample code)
io.on('connection', function(socket){
console.log("user connected");
global.socket = socket;
socket.on('disconnect', function(){
console.log("disconnect");
});
socket.on('my message', function(){
console.log("My message received");
});
});
and on my test route I did
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
if(socket){
socket.emit('response', 'nothing');
}
res.render('index', { title: 'Express' });
});
module.exports = router;
It solved the previous problem of multiple event listener on refresh But most of the time it can not emit the response. And even it emit my browser can not show the result. On client side I did something like this -
var socket = io.connect('http://localhost');
socket.on('response', function(data){
console.log(data);
document.getElementById("change").innerHTML += data;
});
I can see the response in browser console but my browser show the change for a few milliseconds before it disappear.
I think the the main problem is The page loads before establishing socket connection.
I am currently learning node.js and socket.io. So please help me.
Conclusion
I do have plan to add social network features like one to one message, live friends feed update on home page etc using socket.io in future. Please let me know if there is any good documentation or open source project that can help me implementing it.
I am searching for solution for last couple of days but with no luck so far. I am ready to learn any new methodology or fully rewrite my code.
TL;DR
When a user client search for item, push contents to the client that requested the content when new data available. Data is available after processing response from website like "The Movie Database" and "TheTVDB.com" through their API.
You can use the ID of the socket to keep track of which socket to send results to.
Client
When the user then searches for something the ID is included in the query parameters.
<body>
<form>
<!-- Disable the search bar until the socket is connected -->
<input type="search" name="q" placeholder="Search" disabled>
</form>
<div id="results"></div>
<script src="/socket.io/socket.io.js"></script>
<script>
var resultsElement = document.querySelector("#results");
var search = document.querySelector("form [type=search]");
var socket = io("http://localhost:3000");
socket.on("connect", function(){
search.disabled = false;
});
socket.on("results", function(results){
for(var i = 0;i < results.length;i++){
var result = document.createElement("div");
result.textContent = results[i];
resultsElement.appendChild(result);
}
});
document.querySelector("form").addEventListener("submit", function(event){
fetch("/search?socketID=" + encodeURIComponent(socket.id) + "&q=" + encodeURIComponent(search.value));
event.preventDefault();
});
</script>
</body>
Server
When the server receives the search request it gets the socket using the socket ID sent in the query parameters and starts sending results back to the client.
var app = require("http").createServer(handler);
var io = require("socket.io")(app);
var fs = require("fs");
var url = require("url");
app.listen(3000);
function handler(req, res) {
var query = url.parse(req.url, true).query;
if(req.url.startsWith("/search")){
var results = ["things", "stuff", "items"];
// Server-side IDs have "/#" in front of them
var socket = io.sockets.connected["/#" + query.socketID];
if(socket){
// Get and send "search results"
var interval = setInterval(function(){
var popped = results.pop();
if(popped){
socket.emit("results", [query.q + " " + popped]);
}else{
clearInterval(interval);
}
}, 1000);
}
res.writeHead(204);
res.end();
}else{
fs.readFile(__dirname + "/index.html", function(err, data) {
res.writeHead(200);
res.end(data);
});
}
}
I'm totally new to node.js and I want to implement push notification system on a MySql database. I have a notification table in my database. In this table I have store recipient_id that specify the recipient of the notification. Now I want when a new notification with recipient_id is equal to current logged in user's id notify that user. Something like Stackoverflow If you are in the for example java tagged questions, every time a new question with java tag create, a notification appear on top of the page : 1 question with new activity.
Sorry for my poor English. Please help me to implement this system, because I'm new to it.
I have made a simple app like your requirement.
You can get help from following lines of code.You need to understand the basics of code. after that you will easily achieve your target. most of things from your requirement covered in this demo app.
Its not a exact but you will meet your target through this.
In this example a status post by any user will emit to all other users also at same time. we can manipulate it to achieve "1 new status".
make a table in database where your entries to be saved
CREATE TABLE status
(
`status_id` INT NOT NULL AUTO_INCREMENT,
`s_text` TEXT,
`t_status` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY ( `status_id` )
);
//server.js
var app = require("express")();
var mysql = require("mysql");
var http = require('http').Server(app);
var io = require("socket.io")(http);
/* Creating POOL MySQL connection.*/
var pool = mysql.createPool({
connectionLimit: 100,
host: 'localhost',
user: 'root',
password: '',
database: 'fbstatus',
debug: false
});
app.get("/", function(req, res) {
res.sendFile(__dirname + '/index.html');
});
io.on('connection', function(socket) {
console.log("A user is connected");
socket.on('status added', function(status) {
add_status(status, function(res) {
if (res) {
io.emit('new status', status);
} else {
io.emit('error');
}
});
});
});
var add_status = function(status, callback) {
pool.getConnection(function(err, connection) {
if (err) {
connection.release();
callback(false);
return;
}
connection.query("INSERT INTO `status` (`s_text`) VALUES ('" + status + "')", function(err, rows) {
connection.release();
if (!err) {
callback(true);
}
});
connection.on('error', function(err) {
callback(false);
return;
});
});
}
http.listen(3000, function() {
console.log("Listening on 3000");
});
//index.html
<html>
<head>
<title>Socket.io</title>
<script src="/socket.io/socket.io.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
<script src = "http://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
<script>
$(document).ready(function(){
var socket = io();
$("#add_status").click(function(){
socket.emit('status added',$("#comment").val());
});
socket.on('new status',function(msg){
var count = $('#count_status').text();
var valCount = parseInt(count);
if(valCount>=1) {
valCount = valCount+1;
} else {
valCount = 1;
}
var showMsg = '<div id="count_status"> '+valCount+' </div> new status';
$("#show_comments").html(showMsg);
});
});
</script>
</head>
<body>
<div id="comment_box" style = "padding:5%;">
<textarea id="comment" rows="5" cols="70"></textarea><br /><br />
<input type="button" id="add_status" value="Add">
</div>
<div id= "show_comments" class = "jumbotron"></div>
</body>
</html>
Run the app with following command
node Server.js
Now run http://localhost:3000/ in browser and to see the result open a new window in which you post a status and see your new status notification in both the window.
Thanks
Edited: This a great startup tutorial. a few thing needs modification.
connection.release() code ends up unreadable and not working. you should comets or remove it.
2.The actual output in my case:
You can do it 2 ways:
Query the server every n seconds for any new messages. Pass a timestamp of the last time you checked as a parameter and if any notification since the last check, return as json and display them in the client. This is called a pull strategy.
Or you can use websockets which maintains a permanent connection between your client and server, and then you can send notifications to the client from your server code in real-time. See socket.io tutorials. This is called a push strategy.
I'm trying to display a message after or before a redirect. I looked around the site but I found only jquery and php but I can only use the normal java language. In particular I'm trying to use a div that could be good for me. The problem is that the redirect is on the server side (so I cannot call a javascript function or I cannot put a document.getElementByID). Can you help me? Here is my code:
var express = require('express');
var router = express.Router();
var middleware = require('../middleware');
var mongoose = require('mongoose');
var ObjectId = mongoose.Types.ObjectId;
var User = mongoose.model('User');
var config = require("../../config");
var session;
router.all('/', middleware.supportedMethods('GET, POST'));
router.get('/', function(req, res, next) {
res.render('login');
});
router.post('/', function (req, res) {
var post = req.body;
var query = User.where({userName : post.username});
query.findOne(function(err, user){
if (err) { return err}
if (user) {
user.isValidPassword(post.password, function(n, isMatch){
if(isMatch) {
req.session.user_id = user._id;
res.redirect('/library?' + user._id);
} else{
res.redirect('/login');
}
});
}else{
res.redirect('/login');
}
});
});
module.exports = router;
I would put my message on the res.redirect('/login') (both of them) with two different message. I don't know if I have to create a new page, identical, with a div message or I could find a better solution...
I'm trying to display a message after or before a redirect...The problem is that the redirect is on the server side (so I cannot call a javascript function or I cannot put a document.getElementByID).
Exactly. So you can't do that. Instead, you need to return a redirect to a page with your message on it, and then have that page continue on (after a period of time, or after a user action) to the ultimate destination (/login or whatever).
A minimal intermediary page might look like this:
<!doctype html>
<html>
<head>
<title>Some Relevant Title</title>
<meta charset="utf-8"></meta><!-- Or whatever is appropriate -->
<meta http-equiv="refresh" content="15; url=/login">
</head>
<body>
Message goes here. With the refresh above, the page will refresh after 15 seconds.
</body>
</html>