I have a review and submit page where I get data from mysql, send it to my handlebars page as JSON, where I parse and display it.
However, when I plug {{data1}} in my script tag it shows up as
{"id":"32","position":"qweqweq","date":"sadasd&q
where I cant parse it anymore since all the " is now ".
However, though it shows up as perfect JSON if I just plug it straight into the handlebars page as {{data1}}
[{"id":"32","position":"qweqweq","date":"sadasd","howUhear":"advertisement".....
Please help steer me in the right direction, thank you.
my index.js
router.get('/jobappsum', authenticationMiddleware(), function(req, res){
const db = require('../db.js');
const userIDpre = (`req.session.passport.user: ${JSON.stringify(req.session.passport)}`);
var userID = userIDpre.match(/\d+/)[0];
db.query("SELECT * FROM Page1 WHERE id = '"+ userID +"'", function(err, results1, field){
console.log(results1);
sum1 = JSON.stringify(results1);
db.query("SELECT * FROM Page2 WHERE id = '"+ userID +"'", function(err, results2, field){
sum2 = results2;
db.query("SELECT * FROM Page3 WHERE id = '"+ userID +"'", function(err, results3, field){
sum3 = results3;
}) res.render('jobappsum', {
data1: sum1,
data2: sum2,
data3: sum3
});
;
});
});
});
jobappsum.hbs
{{> header }}
<p id="demo"></p>
<script>
var obj = JSON.parse({{data1}});
//{{data1}} " shows up up as " and gives me error
obj = obj[0];
document.getElementById("demo").innerHTML = obj.id + ", " + obj.position;
</script>
{{result}}
//will show up as the correct JSON
Your code:
res.render('jobappsum', {
Your "jobappsum" is meant to output HTML, so it encodes your quotes. It transforms " to " ; as you can see. When you display it in your view, you see " as normal, but it's not the " character itself. It's " ; and is displayed as " in the browser.
So, you should use a renderer that doesn't HTML escape.
If you don't want something in the output escaped in your view, try:
!{data1}
or
{{{data1}}}
within the view.
Or you can use decodeURI() function to unescape the escaped JSON before parsing:
var obj = JSON.parse(decodeURI("{{data1}}"));
If using Swig.js, you can use:
{{ data1|json|raw }}
Related
I'm sure this is a simple error in my syntax but I'm currently using a nodejs function to input into my SQL database, however, while the overall query works, and some variables get input correctly, a couple are input as undefined, which has thrown me for a loop. I'll input the query below and I presume I either added extra punctuation where not required or something.
con.query("INSERT INTO _rounds(roundnum, roundse, roundtk, winner) VALUES('"+ roundnumres +"', '"+ roundse +"', '"+ roundtk +"', '"+ roundwinner +"')", function (err, result) {
});
For more information, the roundnumres and the roundtk variables are the ones inserted as undefined, and are both defined by a random string generator which looks as follows:
function makese(length) {
var roundse = '';
var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var charactersLength = characters.length;
for ( var d = 0; d < length; d++ ) {
roundse += characters.charAt(Math.floor(Math.random() * charactersLength));
}
return roundse;
}
var roundse = makese(20);
Any help would be appreciated!
you could do this. you don't have to concat strings using plus
const query = `INSERT INTO _rounds(roundnum, roundse, roundtk, winner) VALUES('${roundnumres}', '${roundse}, '${roundtk}', '${roundwinner}')"
con.query(query, () => {})
So I have the code, that calls to mySQL based on the route, however it does not work...
app.get("/attitude-chart/:att", function(req, res) {
connection.query("SELECT * FROM actors ORDER BY id WHERE ?",{'attitude':`${req.params.att}`}, function(err, result) {
var html = "<h1>Attitude-chart</h1>";
html += "<ul>";
for (var i = 0; i < result.length; i++) {
html += "<li><p> ID: " + result[i].id + "</p>";
html += "<p>Name: " + result[i].name + " </p></li>";
}
html += "</ul>";
res.send(html);
});
});
results are undefined....
It's not clear what package you're using for MySQL, but it looks to me like your SQL is not well formed.
I would expect your query to look something like this:
connection.query('SELECT * FROM actors WHERE attitude=?', req.params.att, ...)
This will result in an SQL query that looks like:
SELECT * FROM actores WHERE attitude='your value';
In your query, you have no WHERE expression, just a placeholder where an expression should be. I'm not familiar with every MySQL package out there, but every one I know of will require you to spell out what condition you're trying to match.
I fixed it. Swapping WHERE and ORDER BY did the trick!
connection.query("SELECT * FROM actors WHERE ? ORDER BY id",[{'attitude':`${x}`}], function(err, result) {
console.log(result);
var html = "<h1>Attitude-chart</h1>";
html += "<ul>";
for (var i = 0; i < result.length; i++) {
html += "<li><p> ID: " + result[i].id + "</p>";
html += "<p>Name: " + result[i].name + " </p></li>";
}
html += "</ul>";
res.send(html);
});
You don't use a placeholder for the entire comparison expression. And the ORDER BY clause has to be after the WHERE clause.
You need to write:
connection.query("SELECT * FROM actors WHERE attitude = :attitude ORDER BY id ",{'attitude': `${req.params.att}`}, function(err, result) {
The :attitude placeholder is replaced with the value of the attitude property of the object.
And if the column is numeric, you shouldn't put req.params.att in a template literal. You should pass the numeric value to the query.
I have a textfile in my project structure with 10 lines of names
Sarah
Adam
John
Connor
...
And I want to append all those lines as options to my as options
<select id="nameSelect">
<!-- I want them here -->
</select>
my question is.. Would I use pure JavaScript or something like React?
Because what if I wanted to add 100 items to the select, I wouldn't want to hardcode each option.
Here's a simple way of doing it with NodeJS, a popular server-side framework based on JavaScript. The page will be stored at the URL http://localhost:8080:
//For the purposes of this answer, your text file is called names.txt
var http = require("http");
var fs = require("fs");
http.createServer(function (req, res) {
fs.readFile("names.txt", function (err, data) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.write("<select id='nameSelect'">
var namesArray = data.split("\n");
for (var i = 0; i < namesArray.length; i++) {
res.write("<option value='" + namesArray[i] + "'>" + namesArray[i] + "</option>");
}
res.write("</select>");
res.end();
});
}).listen(8080);
If the text file and the file with your options are on the same server, you can indeed show the options based on the text file's content using only JavaScript in the frontend. When your page loads use Ajax to retrieve the file content, and in your callback split by newline and add each line as an option.
<script>
window.onload = function() {
var client = new XMLHttpRequest();
client.open('GET', '/foo.txt');
client.onreadystatechange = function() {
var select = document.getElementById("nameSelect"),
options = client.responseText.split("\n"),
i,
_html = "";
for ( i = 0; i < options.length; i++ ) {
_html += "<option value=" + options[i] +">" + options[i] + "</option>";
}
select.innerHTML = _html;
}
client.send();
}
</script>
In the following code, I have a select query called queryString which retrieves information about some tweets that are already stored in the database. I want to retrieved the hashtags that are mentioned in those tweets so that I show to a user the tweet information along with the its hashtags:
var queryString = 'select Tweet.Label, Tweet.TDate, Tweet.TLink, Author.Lable, Author.ALink from Tweet, Author where Tweet.AuthorID IN (select ID from Author where Lable = ?) AND Author.ID IN (select ID from Author where Lable = ?)';
var query = connection.query(queryString, [term,term], function(err, rows) {
console.log(rows);
//res.write(JSON.stringify(rows));
var tweet = JSON.parse(JSON.stringify(rows));
for(var i in tweet){
res.write("Author: ");
res.write("<a href='" + tweet[i].ALink + "' target='_blank'>" + tweet[i].Lable + "</a> <br/>");
res.write("Date: " + tweet[i].TDate + "<br/>");
res.write("Tweet: " + "<a href='" + tweet[i].TLink + "' target='_blank'>" + tweet[i].Label + "</a> <br/>");
var query1 = connection.query('select Label from Hashtag where ID IN (select HashID from tweethashs where TweetID IN (select ID from Tweet where Label = ?))', [tweet[i].Label], function(err, rows1) {
var tweet1 = JSON.parse(JSON.stringify(rows1));
for(var i in tweet1){
res.write("Hashtag: ");
res.write(tweet1[i].Label);
}
}
);
res.write("<br/><br/>");
}
res.end();
});
What I did is I included a query for the hashtags inside the loop of tweets so that I take the tweet as a parameter for the hashtags query (in where clause). When I run the code, I got the following error:
events.js:154
throw er; // Unhandled 'error' event
^
Error: write after end
at ServerResponse.OutgoingMessage.write (_http_outgoing.js:426:15)
at Query._callback (C:\Users\Nasser\Desktop\Spring Semester\Intelligent Web\
Node JS\SocialSearch.js:58:11)
at Query.Sequence.end (C:\Users\Nasser\Desktop\Spring Semester\Intelligent W
eb\Node JS\node_modules\mysql\lib\protocol\sequences\Sequence.js:96:24)
at Query._handleFinalResultPacket (C:\Users\Nasser\Desktop\Spring Semester\I
ntelligent Web\Node JS\node_modules\mysql\lib\protocol\sequences\Query.js:144:8)
at Query.EofPacket (C:\Users\Nasser\Desktop\Spring Semester\Intelligent Web\
Node JS\node_modules\mysql\lib\protocol\sequences\Query.js:128:8)
at Protocol._parsePacket (C:\Users\Nasser\Desktop\Spring Semester\Intelligen
t Web\Node JS\node_modules\mysql\lib\protocol\Protocol.js:280:23)
at Parser.write (C:\Users\Nasser\Desktop\Spring Semester\Intelligent Web\Nod
e JS\node_modules\mysql\lib\protocol\Parser.js:73:12)
at Protocol.write (C:\Users\Nasser\Desktop\Spring Semester\Intelligent Web\N
ode JS\node_modules\mysql\lib\protocol\Protocol.js:39:16)
at Socket.<anonymous> (C:\Users\Nasser\Desktop\Spring Semester\Intelligent W
eb\Node JS\node_modules\mysql\lib\Connection.js:96:28)
at emitOne (events.js:90:13)
Can someone help me solving this problem
Basically you make several asynchronous db queries in your for loop, but you close your response when the synchronous for loop is ending.So when the db queries end you try to write on an response which is already closed.
var queryString = 'select Tweet.Label, Tweet.TDate, Tweet.TLink, Author.Lable, Author.ALink from Tweet, Author where Tweet.AuthorID IN (select ID from Author where Lable = ?) AND Author.ID IN (select ID from Author where Lable = ?)';
var query = connection.query(queryString, [term,term], function(err, rows) {
console.log(rows);
//res.write(JSON.stringify(rows));
var tweets = JSON.parse(JSON.stringify(rows));
var queries_made = 0;
var queries_success = 0;
tweets.forEach(function(tweet){
connection.query('select Label from Hashtag where ID IN (select HashID from tweethashs where TweetID IN (select ID from Tweet where Label = ?))', [tweet.Label], function(err, rows1) {
res.write("Author: ");
res.write("<a href='" + tweet.ALink + "' target='_blank'>" + tweet.Lable + "</a> <br/>");
res.write("Date: " + tweet.TDate + "<br/>");
res.write("Tweet: " + "<a href='" + tweet.TLink + "' target='_blank'>" + tweet.Label + "</a> <br/>");
var tweet1 = JSON.parse(JSON.stringify(rows1));
for(var j in tweet1){
res.write("Hashtag: ");
res.write(tweet1[j].Label);
}
res.write("<br/><br/>");
queries_success++;
if(queries_made==queries_success)
res.end();
}
);
queries_made++;
})
});
I have added two counter that will track the db queries you requested and the queries that have replied. When those two counters are equal all db transactions and response writes are completed, so you can close the response stream.
Although this is not best practice. You should check the async module or try to use promises with your db queries.
Edit
I changed the code so that the writes occure when the inside queries complete. Be careful now because the order of the writes will not respect the order of the first query but it will write based on what inside query ends first. I must tell you that this is not the best way to accomplish that and you need to read the async module and the promises i told you before. Also take a look at how to mix asynchronous and synchronous operations in javascript!
If you choose to do this by stalling the res.end() you are not sure whether your response will be written in the same order as the tweets are in the array.
The for loop is synchronous but the queries are asynchronous which means they could finish faster than some which started earlier. Which will result theoretically in the writes to happen at random.
What you can use is an async.map.
Basically, instead of that foreach loop you can put something like the following code:
Note: To better understand this first read the async.map code.
//the tweet for which I get the information from DB
var getTweetInfo = function(tweet, callback){
con.query(query, function(err, tweetInformation){
if(err) {
console.log(err);
//with this you are passing the error back into the async.map function. Otherwise it would be lost (Bad javascript :P)
callback("Error getting tweets" + err);
}
else{
//in here you can make any changes to the tweet information before sending it as a response
//this will send the tweetInformation into the results array
callback(null, tweetInformation);
}
});
}
//tweetsArray is the array with tweets
//getTweeetInfo is a function that will get each tweet from the tweets array and will apply the query to it
async.map(tweetsArray, getTweetInfo, function(error, tweetInformationArray){
if (error) {
console.log(error);
}else{
//'results' will hold an array with the information for each tweet in the same order as the initial tweets
res.json({
response: tweetInformationArray
});
}
})
After this you can parse the response on the front-end. The data is consisted, asynchronous (you do not keep the event loop waiting), in order which means you can go through it and display it nicely on the screen.
I'm in the process of redesigning my website, and with this I wanted to update/improve the various scripts involved. One such script is a call to the Twitch API for a set group of streamers, then displaying who's online and, if any are, displaying the first live stream and allow the user to switch between them.
My original script, which works great, was originally constructed by somebody here on StackOverflow. The problem is that instead of guiding me to a usable answer, they just rewrote my code to work in a way that I have a hard time following. I honestly have no idea how the loop they made works. It works, and I use it now, but that's my mistake. I want to start fresh and get a return for each user in an array, then construct things out based on the results of their live status. I don't understand how it is currently being done with this code, and I can't seem to figure out the point where it is saving the return, so I can't properly log it to the console to look at it and use it proper.
Long story short, can anybody help me with a simple return in a loop for each user so I can log it to the console and look at it and use it DIRECTLY instead of saving pieces to a million variables? Here's the code I'm currently using:
$(document).ready(function () {
var casters = ["marcusraven86","whit3rabbit87","dragonbornmonocle","m3ta1head","jimmyjojo7","redshoes","sergeantatams","stevechopz"];
var castersLive = [];
var reqs = $.map(casters, function (userName, i) {
return $.getJSON('https://api.twitch.tv/kraken/streams/' + userName + '.json?callback=?');
})
$.when.apply($, reqs).done(function () {
$.each(arguments, function (i, array) {
var data = array[0];
var userName = casters[i];
console.log(data);
if (data.stream === null) {
$('<div class="streampost"></div>').append(
'<a id="offline' + userName + '" class = "offline" href="http://www.twitch.tv/' + userName + '/profile" title="' + userName + '" target="_blank"></a>').appendTo('#statusblock');
}
else {
castersLive.push(casters[i]);
$('<div class="streampost"></div>').append(
'<a id="online' + userName + '" class = "online" href="http://player.twitch.tv/?channel=' + userName + '" title="' + userName + '" target="stream"></a>').appendTo('#statusblock');
}
});
console.log(castersLive);
if (castersLive.length > 0) {
$('<div class="streamplayer embed-responsive embed-responsive-16by9"></div>').append('<iframe src="http://player.twitch.tv/?channel=' + castersLive[0] +'" name="stream"></iframe><iframe src="http://www.twitch.tv/' + castersLive[0] + '/chat?popout=" frameborder="0" scrolling="no" height="478" width="350" id="chatFrame" name="chatFrame"></iframe>').appendTo('#streamblock');
}
else {}
$('.online').click(function() {
var streamName = $(this).attr('title');
$('#chatFrame').attr('src', 'http://www.twitch.tv/' + streamName + '/chat?popout=');
});
});
});
And here is where I'm trying to restart, but I can't seem to get the call to the API correct. I'm still a bit new to all this, and I also use the Tumblr and YouTube APIs. Each is different, and it throws me off a little.
$(document).ready(function () {
var casters = ["marcusraven86","whit3rabbit87","dragonbornmonocle","m3ta1head","jimmyjojo7","redshoes","sergeantatams","stevechopz"];
var castersLive = [];
for (i=0; i <= casters.length; i++) {
$.get('https://api.twitch.tv/kraken/streams/' + casters[i] + '.json?callback=?'), function ( data ) {
console.log(data);
};
};