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.
Related
I'm trying to make a website using HTML/CSS/JavaScript on the client-side, and use Node.js and SQLite on the server-side.
Below is the code I wrote in 'app.js' which is my server page.
var express = require('express');
var app = express();
var fs = require('fs');
const sqlite3 = require('sqlite3');
const sqlite = require('sqlite');
app.use(express.static('public'))
async function getDBConnection(){
const db = await sqlite.open({
filename: "author.db",
driver: sqlite3.Database
});
return db;
}
app.get('/', async function(req, res){
let db = await getDBConnection();
let authors = await db.all("SELECT * from author");
await db.close();
})
var port = 3000;
app.listen(port, function(){
console.log('server on! http://localhost:' + port);
});
I'm trying to extract the data from the author.db, and use the extracted data in a separate javascript file, which is the 'script.js' file. Is there any way for me to do this? I've tried putting two script tags in my index.html file, but an error appears indicating that the server cannot locate the app.js file.
Below is my code for index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Main Page</title>
<link rel = "stylesheet" type = "text/css" href = "main.css">
</head>
<body id = "i_body">
<div class = "fpage">
<main>
</main>
</div>
<script src = "app.js></script>
<script src = "./script.js"></script>
</body>
</html>
So your app.js is your node server. It runs as a backend server - you don't include it as a reference on your front end. Your front-end has to make a request to the backend server (usually using a library like axios) which will fetch the data that the backend provides you. So in your get '/' section you will want to return a json response with your records. Then on your client side, use a library like axios to fetch the data and then use it how you like.
Edit:
Your server code can look something like this:
var express = require('express');
var app = express();
var fs = require('fs');
const sqlite3 = require('sqlite3');
const sqlite = require('sqlite');
app.use(express.static('public'))
async function getDBConnection(){
const db = await sqlite.open({
filename: "author.db",
driver: sqlite3.Database
});
return db;
}
app.get('/api/authors', async function(req, res){
let db = await getDBConnection();
let authors = await db.all("SELECT * from author");
await db.close();
return res.json(authors)
})
var port = 3000;
app.listen(port, function(){
console.log('server on! http://localhost:' + port);
});
Notice that you are now serving the json off an api endpoint - in this case /api/authors although this can be anything.
Put your client files in the public folder - so index.html and script.js should be there. Your index.html file should look like this:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Main Page</title>
<link rel = "stylesheet" type = "text/css" href = "main.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.21.1/axios.min.js"></script>
</head>
<body id = "i_body">
<div class = "fpage">
<main>
</main>
</div>
<script src = "./script.js"></script>
</body>
</html>
Notice that I have included the CDN for the axios library, and removed the reference to the node part in your client. Your script.js can look like this:
axios.get('http://localhost:3000/api/authors').then((res) => {
console.log(res.data)
})
Here you can see I'm using the axios library to call the backend with the endpoint that I mentioned before /api/authors. It gets the json as res.data. At that point you can do whatever you want to it. Hope that helps!
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'm using a Node.js server to show an HTML file. The HTML uses a Javascript file to get some info but I'm not being able to access that file. Here's my index.html file:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Swarm Profile</title>
</style>
</head>
<body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="/js/script.js"></script>
</body>
</html>
And my Node.js server file:
var http = require('http');
var fs = require('fs');
const hostname = '127.0.0.1';
const port = 9000;
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/html');
fs.createReadStream("./index.html").pipe(res);
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
What should I use to be able to access the script.js file?
There are many static file handler modules already in node, take a look at:
Node static modules
Most popular are: Node-Paperboy and Node-Static
Using node static is as simple as:
var static = require('node-static');
var file = new(static.Server)('./public');
require('http').createServer(function (request, response) {
request.addListener('end', function () {
file.serve(request, response);
});
}).listen(8080);
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>
I'm currently working on a project and having some issues with my code ..
My problem: My node.js is analysing a txt file and reading coordinates out of it .. those coordinates should be displayed in a graph in an html file .. both codes are created, but how do I connect them?
node.js:
var fs = require('fs');
function readLines(input, done) {
var arr = [];
var remaining = '';
input.on('data', function(data) {
remaining += data;
var index = remaining.indexOf('\n');
while (index > -1) {
var line = remaining.substring(0, index);
remaining = remaining.substring(index + 1);
func(line);
index = remaining.indexOf('\n');
}
});
input.on('end', function() {
if (remaining.length > 0) {
func(remaining);
done(arr);
}
});
function func(data) {
arr.push(data.split(/\s+/g)); //Splitfunktion für Komma
}
}
var input = fs.createReadStream('test.txt');
readLines(input, done);
//abschließen
function done(arr) {
var obj = {};
var key1 = arr[0][0];
var key2 = arr[0][1];
obj[key1] = [];
obj[key2] = [];
arr.shift();
arr.forEach(function (item) {
obj[key1].push(item[0]);
obj[key2].push(item[1]);
});
console.log('X:', obj[key1]);
console.log('Y:', obj[key2])
}
Html file:
<!doctype html>
<html>
<head>
<!-- ... -->
</head>
<body>
<!-- ..... -->
<script>
var lineChartData = {
labels : [380, 390 ..<!-- X-Coordinates here -->
datasets : [
{
data : [0.5,
0.6,
0.7,
<!-- Y-Coordinates here -->
]
}
]
}
<!-- ... --->
</script>
</body>
</html>
I hope you can help!
Greetings,
JS
I suggest you use expressjs. Using nodejs to create web application is quite low-level. You have to install express via node npm install express and go from there.
Some code snipped to help
var express = require('express');
var app = express();
app.use(express.bodyParser());
app.set('view engine', 'ejs');
app.register('.html', require('ejs'));
app.get('/', function(req, res) {
// Handle file reading in here and return object
res.render('index.html', {obj: obj}); //where object is the obj is the object holding the arrays
});
app.listen(8080, function() {
console.log('Server running at http://127.0.0.1:8080/');
});
then in your index.html do .. inside script tags.
<script>
console.log(<%= cordinates.obj %>);
</script>
DISCLAIMER: I haven't tested this but it's just to help you on your way