assign Json value to a variable using $.each() - json

I am trying to pass the result of this query as a Json string to Jquery so that I can assign the value to a JQuery variable. Actually there will be more than one key:value pair but I am illustrating my problem with a single pair for simplicity. I am able to console.log the index and value however when I try to assign the value to a variable I get an "undefined" message. I have done this successfully elsewhere and am not sure what i am missing here:
$query = (
"SELECT MedCondPrimary, Count(MedCondPrimary) as Count
FROM Comments
WHERE MedCondPrimary='Arthritis'");
$result = mysqli_query($dbc, $query);
WHILE($rows = mysqli_fetch_array($result)) {
$medcond = $rows['MedCondPrimary'];
$array3[$medcond] = $rows['Count'];
};
$json_count=json_encode($array3);
echo $json_count; // {"Arthritis":"26"}
JQ:
var tally = ;
console.log(tally);// Object { Arthritis="26"} should be a string?
$.each(tally, function(index, value) {
console.log(index+":"+value); //Arthritis:26
var arthritis = value.Arthritis;
console.log(arthritis); //undefined
});

Your jQuery code should be using each() instead of $.each() here.
$( tally ).each(function( index, obj ) {
console.log( index + ":" + obj.Arthritis); // Arthritis:26
var arthritis = obj.Arthritis;
console.log( arthritis ); // 26
});
each() passes the object while $.each() passes property-value pairs for an object. You're $.each() at the other place must be working because you passed it an array as shown below:
// iterating an array
$.each( [{Arthritis:26}], function( index, obj) {
console.log( obj.Arthritis ); // 26
});
PHP Edit :
$json_count=json_encode($array3);
echo "[" . $json_count . "]";

Related

Table data in HTML does not separate well

I was working with a table in HTML and I have the following doubt: I am taking the data from a JSON array: {"key":["1","2","3"],"values":["4","5","6"]} and when trying to insert them into the table instead of putting each data in a column all the data is put in the first column, the JS code that I am using to insert the data in the table is:
var idtabla = document.getElementById("idtabla")
idtabla.innerHTML += window.location.href.split("/tabla/")[1]
function getJson(){
var id = window.location.href.split("/tabla/")[1]
var table = document.getElementById("table")
$.get( `/json`, (data) => {
if(data.error){
idtabla.innerHTML = 404 + ", tabla no encontrada"
} else {
var keys = data.key.forEach(element => {
table.innerHTML += `<tr><td>${element}</td>`
});
var values = data.values.forEach(element => {
table.innerHTML += `<td>${element}</td></tr>`
});
}
})
}
and the result it gives me is this:
How could it be solved? Thanks a lot.
There are two problems.
First, you can't add partial HTML to innerHTML like that. Whenever you assign to innerHTML, it parses the result completely. If there are any unclosed tags, they're closed automatically. If you want to build the HTML incrementally, you should do it by appending to a string, then assign the completed string to innerHTML.
Second, you're appending all the values all the values after all the keys, so they won't be in matching rows. You need to append both the key and value in the same loop. Since forEach() passes the array index to the callback function, you can use that to index into the other array.
let tableHTML = '';
data.keys.forEach((key, i) => {
tableHTML += `<tr><td>${key}</td><td>${data.values[i]}</td></tr>`;
});
table.innerHTML = tableHTML;

The array does not output properly

let test = [];
d3.csv("cgvList.csv", function (data) {
if (data.poi_nm == "CGV") {
let obj = {};
obj.content = '<div>' + data.branch_nm + '</div>';
test.push(obj);
}
});
console.log(test);
console.log("test[0] : " + test[0]);
console.log("test.length : " + test.length);
[enter image description here][1]
I made the csv file into an object array.
And as a result of outputting the array, the array was output well,
enter image description here
but when outputting index 0, undefined came out and the length of the array was also 0.
It was printed properly when it was printed from the console.
What's the problem?
enter image description here
Without a jsfiddle or sandbox to play with, I can't tell exactly what is going on, but what I believe is happening is a mix of two things:
d3.csv is an async function, and therefore returns a promise.
The function you pass on to d3.csv is supposed to tell the function how to parse every element in the csv, and should return the parsed object, not add it to an external array or anything like that. Every element you return in that function will be an element in your resulting array
There's (at least) two possible ways you can deal with this:
await the async function, and its return value will be your required value, something like
const test = await d3.csv("cgvList.csv", function (data) {
if (data.poi_nm == "CGV") {
let obj = {};
obj.content = '<div>' + data.branch_nm + '</div>';
return obj;
}
});
console.log(test);
console.log("test[0] : " + test[0]);
console.log("test.length : " + test.length);
Notice that here the function you pass onto d3.csv returns the object in the way you want to format it!
Do your logic in a .then statement, which also waits for the promise to be fulfilled:
d3.csv("cgvList.csv", function (data) {
if (data.poi_nm == "CGV") {
let obj = {};
obj.content = '<div>' + data.branch_nm + '</div>';
return obj;
}
}).then((test) => {
console.log(test);
console.log("test[0] : " + test[0]);
console.log("test.length : " + test.length);
});

Parse random String & return Value (JSON)

Edit: It works pretty well now and this makes it possible to reference URLs in a JSON file and return their related pairs (e.g game name / year / image url). Here's the code.
AFRAME.registerComponent('jfetch', {
schema: {},
init: function () {
var url = 'json/text.json';
var request = new XMLHttpRequest();
request.open( 'GET', url, true );
request.addEventListener( 'load', function ( event ) {
var jsongames = JSON.parse( event.target.response )
var keys = Object.keys(jsongames);
var random = jsongames[keys.length * Math.random() << 0];
var games = random.Title + ' (' + random.Developer + ')'
var textEntity = document.querySelector('#text');
textEntity.setAttribute("value", games)
var gurl = random.Imageurl
var sceneEl = document.querySelector('a-scene');
sceneEl.querySelector('a-box').setAttribute('material', {src:gurl});
} );
request.send( null );
}
});
Thanks for the help everyone!
Original Question: I would like to fetch a random "Title" string in my Json file and return its corresponding value. I know the simple test code works but I have no idea how to apply it to an array with lots of objects and to add the random parsing element. Can someone please help me with a solution? This is my remix file.
AFRAME.registerComponent('json-text-loader', {
schema: {},
init: function () {
var textEntity = document.querySelector('#text');
var url = 'json/text.json';
var request = new XMLHttpRequest();
request.open( 'GET', url, true );
request.addEventListener( 'load', function ( event ) {
var jsonGames = JSON.parse( event.target.response )
textEntity.setAttribute("value", jsonGames.Title)
} );
request.send( null );
}
});
You can not manipulate JSON file as you would with an object, because JSON is a string. Thats why we parse them (converting into Javascript object).
From your question I assume that you want to get a random value of key-value pairs, where key is a Title. In that case, first you parse JSON response (as you do already - var jsonGames = JSON.parse( event.target.response )). So now you have your Javascript object to work with - jsonGames and all what is left is to get that random key of it. To do that you can, for ex:
var jsonGames = JSON.parse( event.target.response )
var keys = Object.keys(jsonGames);
var random = jsonGames[keys[keys.length * Math.random() << 0]];
textEntity.setAttribute("value", random.Title)
Please comment if something is not right.

Understanding ES6 tagged template literal

Following code snippet is used on Mozilla (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals) to explain Tagged Template literal, please help me understand what following function is doing, i am unable to get the actual flow of the function, since they have used keys.foreach and when i inspected in Chrome, keys was a function, so not able to understand
function template(strings, ...keys) {
return (function(...values) {
var dict = values[values.length - 1] || {};
var result = [strings[0]];
keys.forEach(function(key, i) {
var value = Number.isInteger(key) ? values[key] : dict[key];
result.push(value, strings[i + 1]);
});
return result.join('');
});
}
var t1Closure = template`${0}${1}${0}!`;
t1Closure('Y', 'A'); // "YAY!"
var t2Closure = template`${0} ${'foo'}!`;
t2Closure('Hello', {foo: 'World'}); // "Hello World!"
Most of the complexity in the example comes from the overloaded function and the forEach invocation, not from the tagged template literals. It might better have been written as two separate cases:
function dictionaryTemplate(strings, ...keys) {
return function(dict) {
var result = "";
for (var i=0; i<keys.length; i++)
result += strings[i] + dict[keys[i]];
result += strings[i];
return result;
};
}
const t = dictionaryTemplate`${0} ${'foo'}!`;
t({0: 'Hello', foo: 'World'}); // "Hello World!"
function argumentsTemplate(strings, ...keys) {
is (!keys.every(Number.isInteger))
throw new RangeError("The keys must be integers");
return function(...values) {
var result = "";
for (var i=0; i<keys.length; i++)
result += strings[i] + values[keys[i]];
result += strings[i];
return result;
};
}
const t = argumentsTemplate`${0}${1}${0}!`;
t('Y', 'A'); // "YAY!"
Template is a custom function defined by us to parse the template string, whenever a function is used to parse the template stringThe first argument of a tag function contains an array of string values. The remaining arguments are related to the expressions. so here specifically we have written the function to that given output I had got confused because when in inspected keys inside the forEach, i got a function in console, but inspecting the function before forEach gave keys as the array of configurable string ${0} and ${1} in first example

jQuery UI autocomplete using csv with two fields

I'm trying to set up an autocomplete that's getting its data from a csv. The csv has a list of restaurant names and food types. I've gone over some of the other posts here at SO, and the autocomplete documentation, but I think it's the two fields in the csv, rather than one field that is tripping me up.
Example csv data:
McDonald's,Fast Food
Olive Garden,Italian
Manny's,Steakhouse
Carino's,Italian
etc...
The user should be able to search by either food type or restaurant name:
<body>
<br>
<br>
<label id="lblSearchRestaurant" for="txtSearchRestaurant">Search for a Restaurant</label>
<input type="text" id="txtSearchRestaurant">
</body>
Here's what I've tried for the autocomplete setup:
$(function() {
$( "#txtSearchRestaurant" ).autocomplete({
source:searchRestaurant.php,
select: function( event, ui ) {
$( "#search" ).val( ui.item.label + " / " + ui.item.actor );
return false;
}
}).data( "ui-autocomplete" )._renderItem = function( ul, item ) {
return $( "<li>" )
.data( "item.autocomplete", item )
.append( "<a><strong>" + item.label + "</strong> / " + item.actor + "</a>" )
.appendTo( ul );
};
});
I need to serve the data using a PHP script. Here's what I have at this point:
<?php
$header = NULL;
$restaurants = array();
if (($file = fopen('restaurants.csv', 'r')) !== FALSE) {
while (($row = fgetcsv($file, 1000, ',')) !== FALSE) {
if(!$header)
$header = $row;
else
$data[] = array_combine($header, $row);
}
fclose($file);
}
$term = $_GET['term'];
foreach($restaurants as $k=>$v) {
if(preg_match("/^$term/i", $v)) { $return[] = $v; }
}
foreach($restaurants as $k => $v) {
if(preg_match("/$term/i", $v)) { $return[] = $v; }
}
echo json_encode(array_values(array_unique($return)));
None of the above has worked, so I tried formating the restaurant data in to an array, rather than just comma-separated values:
[
{name:"McDonald's",type:"Fast Food"},
{name:"Olive Garden",type:"Italian"},
{name:"Manny's",type:"Steakhouse"},
{name:"Carino's",type:"Italian"}
];
I tried that locally in the <script> tag and in a separate file, but neither worked.
So, none of the above worked for me, but I'm not the best at arrays yet and for that matter, using JSON data, so I probably don't have the php script set up properly.
I'd appreciate it if someone could point me in the right direction here.
Thanks.
Note to potential answers:
The jquery UI autocomplete, the format of the incoming data (as described above) and using PHP to get the data from the csv to the autocomplete are all requirements for this. Those three stipulations are, unfortunately, not under my control.
Here's a jsfiddle that I hope does what you want: http://jsfiddle.net/L8L6k/
The javascript has a variable "data" at the top that you will need to populate with your data, using PHP (I believe you said you could do this.)
This data is then combined into two variables:
var autocomp = new Array();
var hash = new Array();
for (var i=0; i < data.length; i++)
{
autocomp[i] = data[i].name + ' ' + data[i].type;
hash[autocomp[i]] = data[i];
}
1) A simple array, autocomp, that is just a concatenation of the two values, name and type. This is passed to the JQuery UI autocomplete as the source. This way autocomplete will search both your "item" and "type".
2) An associative array, hash, which associates the data object with the concatenated value.
Both the select function and the renderItem function use this hash to get the original data object:
$( "#txtSearchRestaurant" ).autocomplete({
source:autocomp,
select: function( event, ui ) {
var d = hash[ui.item.label];
$( "#txtSearchRestaurant" ).val( d.name + " / " + d.type );
return false;
}
}).data( "ui-autocomplete" )._renderItem = function( ul, item ) {
var d = hash[item.label];
return $( "<li>" )
.data( "item.autocomplete", d )
.append( "<a><strong>" + d.name + "</strong> / " + d.type + "</a>" )
.appendTo( ul );
};
Assuming you return array from the php (the same format that you mention in the question).
Then add this to your <script>:
function both(Restaurant) {
return Restaurant.name + ',' + Restaurant.type ;
}
$( "#txtSearchRestaurant" ).autocomplete({
source:
function( request, response ) {
$.getJSON( "/searchRestaurant.php", function(data) {
response(data.map(both));
});
}
});
Or if you need help in both PHP and javascript, first try sending array consisting of restaurant name and type as a single string element like this :
[
"McDonald's,Fast Food",
"Olive Garden,Italian",
"Manny's,Steakhouse",
"Carino's,Italian"
]
In PHP searchRestaurant.php you can do following to get the above format quickly :
$lines = file('restaurants.csv', FILE_IGNORE_NEW_LINES);
echo json_encode($lines);
In <script> add :
$( "#txtSearchRestaurant" ).autocomplete({
source:
function( request, response ) {
$.getJSON( "/searchRestaurant.php", response);
}
});
I'm not that familiar with PHP, but this generally seems like you are unclear on the concepts. Note to readers: lack of response often indicates an unclear formulation of the question.
Correct me if I'm wrong, but here is how I understand the problem from your description:
You have a CSV of <restaurant>,<cuisine> pairs.
You have an omnibox on a web page where a user can enter restaurant or cuisine.
You want the omnibox to autocomplete based on the CSV.
You want to use the jQuery autocomplete widget to help with this.
The code you have presented tells a different story. The PHP code seems to be doing pretty much nothing. It stuffs a lot of data from a file into a data[] and then does nothing with it. I have no idea what that function produces.
Setting that aside, the HTML you present is a <body> block that contains an input type and a label for that type. (That's okay for this kind of discussion.)
The JavaScript/jQuery, however, is barely related. I don't see why UI items are expected to have a label and an actor. The general display of the auto-complete suggests you want to keep the restaurant and cuisine together and show them as a single selector but you want to have them select on either. This is not something the widget provides "straight out of the box" but it has hooks where you can add code to accomplish what you want.
A good place to start is to realize that while the widget is helpful, it is not meant to deal with multivalued objects. You're going to have to do some significant customization.
I think the keys in the returned array should be 'label' and 'value'.
Maybe you could replace:
$data[] = array_combine($header, $row);
by
if (preg_match("/^$term|$term/i", $row))
$return[] = array('label'=>$header,'value'=>$row);
So it becomes (untested):
<?php
$header = NULL;
$return = array();
$term = $_GET['term'];
if (($file = fopen('restaurants.csv', 'r')) !== FALSE) {
while (($row = fgetcsv($file, 1000, ',')) !== FALSE) {
if(!$header)
$header = $row;
else
if (preg_match("/^$term|$term/i", $row))
$return[] = array('label'=>$header,'value'=>$row);
}
fclose($file);
}
echo json_encode(array_values(array_unique($return)));
?>