First a Heads Up! I am very new to the world of node.js and socket.io
I have a json file which contains following data for example:-
{
"football": {
"id": 1,
"home": "Liverpool",
"away": "Chelsea",
"score": "1-0",
"last scorer":"Gerrard"
}
}
This file is updated live on few seconds basis.
What i really want to achieve is to parse this json and update the same to html on client side, in addition to that i want to listen for any changes in json file and update the same again to html client side. How can i achieve this, sorry if the question seemed dumb enough, but any suggestion can help.
i finally found something and with a little tweak and researching other answers i have finally made a working code
First a brief review of what this code does
watches your json file (in this case sports.json)
if change detected then only reads the json file (in this case sports.json)
then emits the read json file to connected clients
on the client side the magic begins as soon as you make changes to your json file
PS: There is a discussion regarding fs.watch firing twice on manual editing and saving (i will come up with a workaround soon and update here)
Server Side
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var jf = require('jsonfile'); //jsonfile module
var fs = require('fs'); //require file system
app.get('/', function(req, res) {
res.sendFile(__dirname + '/index.html');
});
io.sockets.on('connection', function(socket) {
fs.watch("sports.json", function(event, fileName) { //watching my sports.json file for any changes
//NOTE: fs.watch returns event twice on detecting change due to reason that editors fire 2 events --- there are workarounds for this on stackoverflow
jf.readFile('sports.json', function(err, data) { //if change detected read the sports.json
var data = data; //store in a var
console.log('sent') //just for debugging
socket.volatile.emit('notification', data); //emit to all clients
});
});
});
http.listen(3000, function() { //listen to 3000
console.log('listening on *:3000');
});
Client Side:
<!doctype html>
<html>
<head>
<title>Socket.IO data</title>
<body>
<p id ="data">A data will appear here on change</p>
<script src="https://cdn.socket.io/socket.io-1.2.0.js"></script>
<script src="http://code.jquery.com/jquery-1.11.1.js"></script>
<script>
var socket = io.connect('http://localhost:3000'); //you can replace localhost with your public domain name too!!
socket.on('notification', function (data) {
$('#data').text(data.football.home); //Liverpool
});
</script>
</body>
sports.json File
{
"football": {
"id": 1,
"home": "Liverpool",
"away": "Chelsea",
"score": "1-0",
"last scorer":"Gerrard"
}
}
(Sorry for the little-detailed answer, I'm having computer problems and it's hard to do much; I'll edit it after they're resolved and everything stops crashing)
To look for a change in the file, try something like: Monitor file change through AJAX, how? or Check if file has changed using HTML5 File API
Server file:
var EventEmitter = require('events').EventEmitter;
var footballWatcher = new EventEmitter();
io.on('connection', function (client) {
//
//Existing Code
//
//Node.js Event listener:
footballWatcher.on('update', function(){
io.emit('footballUpdate', footballData);
});
//Code to look for a change in the file, use this in it:
if(updated){
footballWatcher.emit('update');
});
Client File:
//
//Existing Code (connections, methods, emits and responses, etc.)
//
socket.on('football', function(footballJSONData){
//JSON interpretation
});
Related
The question arises from this note:
Someone here suggested using div's. The HTML requirement is very
skeletal. The 3D display is basically canvas, but it requires seven
three.js files, ten js files of my own making to exchange parameters
and other variables with the global variable and .dae collada files
for each of the 3D models you can see. If they could be linked in like
jQuery that might be the solution but I wonder about conflicts.
on Questions on extending GAS spreadsheet usefulness
principally, if they can be linked like jQuery part
The files to be linked are on myDrive. The thinking is that if I can copy the files into GAS editor, it seems as secure and more flexible to bring them into the html directly.
code.gs
function sendUrls(){
var folder = DriveApp.getFoldersByName("___Blazer").next();
var sub = folder.getFoldersByName("assembler").next();
var contents = sub.getFiles();
var file;
var data = []
while(contents.hasNext()) {
file = contents.next();
type = file.getName().split(".")[1];
url = file.getUrl();
data.push([type,url]);
}
return data;
}
html
google.script.run.withSuccessHandler(function (files) {
$.each(files,function(i,v){
if(v[0] === "js"){
$.get(v[1])
}
})
})
.sendUrls();
The first url opens the proper script file but the origin file is not recognisable to me.
I am not sure that this is a proper answer as it relies on cors-anywhere, viz:
function importFile(name){
var myUrl = 'http://glasier.hk/cors/tba.html';
var proxy = 'https://cors-anywhere.herokuapp.com/';
var finalURL = proxy + myUrl;
$.get(finalURL,function(data) {
$("body").append(data);
importNset();
})
}
function importNset(){
google.script.run
.withSuccessHandler(function (code) {
path = "https://api.myjson.com/bins/"+code;
$.get(path)
.done((data, textStatus, jqXHR) => {
nset = data;
cfig = nset.cfig;
start();
})
})
.sendCode();
}
var nset,cfig;
$(document).ready(function(){
importFile();
});
but it works, albeit on my machine, using my own website as the resource.
I used the Gas function in gas Shop to make the eight previously tested js files into the single tba.html script only file. I swapped the workshop specific script files for those needed for google.script.run but otherwise that was it. If I could find out how to cors-enable my site, I think I might be able to demonstrate how scripts might be imported to generate different views from the same TBA and spreadsheet interfaces.
In my app I have a namespaced application and there's information or metadata myApp carries on it that might be useful to devpane.
window.myApp = new App();
How can I relay or send the following information to the devtool.js?
window.myApp.metadata; // information
And can I send a request from the devtool with a function that customizes the serialization of that metadata?
I've seen similar posts with the solution below, which returns null when I tried it.
chrome.devtools.inspectedWindow.eval("window.myApp", {
useContentScriptContext: true
})
NOTE: If a sample template can be provided that would be wonderful.
This is how I've solved this. It feels more complicated than necessary, but it does work.
In the context of the inspected window
Based on this question.
This is where you've got access to window.myApp.metadata and can put it into the data object.
var event = new CustomEvent("RebroadcastExtensionMessage", {data: ""});
window.dispatchEvent(event);
In the content script
This just forwards the data to the background page.
window.addEventListener("RebroadcastExtensionMessage", function(evt) {
chrome.runtime.sendMessage(evt)
}, false);
In the background page
Based on the Chrome docs.
chrome.runtime.onConnect.addListener(function(devToolsConnection) {
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
devToolsConnection.postMessage(request)
});
})
In devtools.js
var backgroundPageConnection = chrome.runtime.connect({
name: "devtools-page"
});
backgroundPageConnection.onMessage.addListener(function (message) {
// Data has arrived in devtools page!!
});
I am using IBM Bluemix to make a web service for a school project.
I need to transform the .csv data I have in a directory in my computer into a .json file, so I can manipulate this information.
I am using the fast-csv package for Node JS, but I am having trouble with the code.
In the end of my .js file, there is a piece of code that is supposed to get the .csv file and convert it to JSON. I obtained it in the fast-csv documentation webpage.
When I run it, nothing happens and I can't fin out why. How can I check if the code is really getting the .csv file and transforming it into a .json one?
The Cambio.csv file is in the same directory of my .js one.
// Hello.
//
// This is JSHint, a tool that helps to detect errors and potential
// problems in your JavaScript code.
//
// To start, simply enter some JavaScript anywhere on this page. Your
// report will appear on the right side.
//
// Additionally, you can toggle specific options in the Configure
// menu.
function main() {
return 'Hello, World!';
}
main();/*eslint-env node*/
//------------------------------------------------------------------------------
// node.js starter application for Bluemix
//------------------------------------------------------------------------------
// HTTP request - duas alternativas
var http = require('http');
var request = require('request');
// cfenv provides access to your Cloud Foundry environment
// for more info, see: https://www.npmjs.com/package/cfenv
var cfenv = require('cfenv');
//chama o express, que abre o servidor
var express = require('express');
// create a new express server
var app = express();
// serve the files out of ./public as our main files
app.use(express.static(__dirname + '/public'));
// get the app environment from Cloud Foundry
var appEnv = cfenv.getAppEnv();
// start server on the specified port and binding host
app.listen(appEnv.port, '0.0.0.0', function() {
// print a message when the server starts listening
console.log("server starting on " + appEnv.url);
});
app.get('/home1', function (req,res) {
http.get('http://developers.agenciaideias.com.br/cotacoes/json', function (res2) {
var body = '';
res2.on('data', function (chunk) {
body += chunk;
});
res2.on('end', function () {
var json = JSON.parse(body);
var cotacao = json["bovespa"]["cotacao"];
var CotacaoDolar = json["dolar"]["cotacao"];
var VariacaoDolar = json["dolar"]["variacao"];
var CotacaoEuro = json["euro"]["cotacao"];
var VariacaoEuro = json["euro"]["variacao"];
var Atualizacao = json["atualizacao"];
console.log('url', req.originalUrl);
obj=req.query;
DolarUsuario=obj['dolar'];
RealUsuario=Number(obj['dolar'])*CotacaoDolar;
EuroUsuario=obj['euro'];
RealUsuario2=Number(obj['euro'])*CotacaoEuro;
if (VariacaoDolar<0) {
recomend= "Recomenda-se, portanto, comprar dólares.";
}
else if (VariacaoDolar=0){
recomend="";
}
else {
recomend="Recomenda-se,portanto, vender dólares.";
}
if (VariacaoEuro<0) {
recomend2= "Recomenda-se, portanto, comprar euros.";
}
else if (VariacaoEuro=0){
recomend2="";
}
else {
recomend2="Recomenda-se,portanto, vender euros.";
}
res.render('cotacao_response.jade', {
'CotacaoDolar':CotacaoDolar,
'VariacaoDolar':VariacaoDolar,
'Atualizacao':Atualizacao,
'RealUsuario':RealUsuario,
'DolarUsuario':DolarUsuario,
'CotacaoEuro':CotacaoEuro,
'VariacaoEuro':VariacaoEuro,
'RealUsuario2':RealUsuario2,
'recomend':recomend,
'recomend2':recomend2
});
var csv = require("fast-csv");
csv
.fromPath("Cambio.csv")
.on("record", function(data){
console.log(data);
})
.on("end", function(){
console.log("done");
});
});
});
});
The code did not work because it was missing views engine setup.
After adding the following lines after var app = express();:
// view engine setup
var path = require('path');
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
and creating a sample Cambio.csv on the application root directory (same dir as app.js):
$ more Cambio.csv
mercado,cotacao,variacao
bovespa,1234,-2.3
dolar,3.777,0.23
euro,4.233,0.12
I run node app.js and point my browser to:
http://http://localhost:6006/home1
Output was:
$ node app.js
server starting on http://localhost:6006
url /home1
[ 'mercado', 'cotacao', 'variacao' ]
[ 'bovespa', '1234', '-2.3' ]
[ 'dolar', '3.777', '0.23' ]
[ 'euro', '4.233', '0.12' ]
I am currently trying to figure out how I can retrieve a single value from a sap.ui.model.json.JSONModel
in my main view:
var gConfigModel = new sap.ui.model.json.JSONModel();
var getConfigCallback = function(config) {
gConfigModel.setData(config);
};
oController.getConfiguration(getConfigCallback);
console.log(gConfigModel);
in my controller:
getConfiguration : function(callback) {
var sServiceUrl = "/sap/opu/odata/sap/xxx/ConfigurationSet('Initialize')";
var config = {};
callback(config);
$.getJSON(sServiceUrl).done(function(data) {
config = data.d;
callback(config);
});
},
In my console.log statement I can see that the data was successfully passed from the backend and successfully set to the JSON model. My requirement is to store the value of attribute Editable in a single variable.
I already tried gConfigModel.getProperty('/'), didnt work. tried to access gConfigModel.oData was undefined .. How can I store it in a single value?
Solution Comment: If you catch data from a backend, you have to take care how long it takes. data can be available later then expected, in my case I added 1s timeout, afterwards I can access the property easily
setTimeout(function() {
console.log(gConfigModel.getProperty('/Editable'));
}, 1000);
I wouldn't advise using the model's getData() method since it is deprecated.
A much better solution is to use gConfigModel.getProperty("/Editable")
(I'm using the root slash here since your property resides in the root of your model)
In the same way, you can also set your data:
gConfigModel.setProperty("/Editable", <your new value>) instead
First of all, thanks for the effort to find solutions of our Problems! (at least, those regarding It stuff.. :) )
I've found a solution which I think is a little bit more save because the timeout is maybe somewhat arbitrary - it would depend on the machine or the amount of data that is to be fetched?
Therefore, I am using an attachRequestCompleted function:
with sUrl_2="path-to-my-service";
var oModel_2 = new sap.ui.model.json.JSONModel(sUrl_2);
oModel_2.attachRequestCompleted(function(data) {
//now, i can access the data stored in the oModel_2, either by getProperty, or by DOM: oModel_2.oData.d.Vendor
gv_selLieferant = oModel_2.getProperty("/d/Vendor");
gv_selEinkOrg = oModel_2.getProperty("/d/PurchOrg");
gv_selEinKGru = oModel_2.getProperty("/d/PurGroup");
});
<script src="https://openui5.hana.ondemand.com/resources/sap-ui-core.js" id="sap-ui-bootstrap" data-sap-ui-theme="sap_bluecrystal" data-sap-ui-libs="sap.m"></script>
<script>
function getConfiguration(callback) {
var sServiceUrl = "/sap/opu/odata/sap/xxx/ConfigurationSet('Initialize')";
var config = {};
var data = {
"d": {
"_metadata": "",
"Backup01": "01",
"Editable": "True"
}
};
setTimeout((function() {
config = data;
callback(config);
})(), 2000);
};
var gConfigModel = new sap.ui.model.json.JSONModel();
var getConfigCallback = function(config) {
gConfigModel.setData(config);
alert(gConfigModel.getProperty("/d/Editable"));
};
getConfiguration(getConfigCallback);
</script>
i use fetch from backbone.js to load a json model but success will not hit.
var DialogModel = Backbone.Model.extend({
url : function() {
return '/messages/getDialog';
},
parse : function(res) {
return res.dialog;
}
});
var DialogView = Backbone.View.extend({
el: $("#page"),
initialize: function() {
var onDataHandler = function() {
this.render();
};
this.model = new DialogModel();
this.model.fetch({ success : onDataHandler});
},
render: function(){
var data = {
dialogModel : this.model
};
var form = new Backbone.Form({
model: data
});
$(this.el).html(form.render().el);
}
});
What happens now:
DialogView initialize is called.
this.model.fetch is called but the onDataHandler function will not be hit if success.
/messages/getDialog throws a json file back.
The json file is loading well as i can see in the network browser.
Thanks for your help!
Oleg
The problem you're having is due to a typical JS gotcha and not related to Backbone itself. Try
var that = this;
this.model.fetch({
success : function () {
that.render();
}
});
The way you're currently passing onDataHandler is problematic as it will cause this to refer to the global object instead of the DialogView, when the function is called.
This fiddle demonstrates the problematic version vs one that works.
(You may also want to take a look at JS strict mode which can shield you from this type of errors.)
Even better is to listen for an event:
this.model.on("sync", this.render).fetch();
I ran across this question while looking for something else, but the currently accepted answer drives me nuts. There's no good reason to be sprinkling this and that all over your code. Backbone (underscore) includes a context parameter that you can bind to.
that = this makes no sense. If you must implement obsolete 2007-era Crockford patterns, then say var self = this. Saying that = this is like saying left = right. Everyone Stop.