Dimple.js doesn't like my Array - javascript

I have data.json in this format:
{
"Users": [
{
"userName": "Herbie",
"weigh-in data": [
{ "date": "2016.01.04", "weight": "114.3" },
{ "date": "2016.01.05", "weight": "114.6" },
{ "date": "2016.01.06", "weight": "114.9" }
]
},
{
"userName": "Wayne",
"weigh-in data": [
{ "date": "2016.02.01", "weight": "120.3" },
{ "date": "2016.02.05", "weight": "123.6" },
{ "date": "2016.02.06", "weight": "123.9" }
]
}
]
}
// etc., more user objects
In my application: a selection of a user is made, an ajax call gets this data, I loop thru it to get only the selected user's weigh-in data, and I'm successfully rendering this data to a table.
Now I'm trying to use the same result in a Dimple chart but Dimple evidently doesn't like my chartData array:
var dataObj = JSON.parse(jsonData);
var usersArray = dataObj.Users;
var chartData = [];
// etc. SNIP
for (var obj of usersArray) {
if (obj.userName === selUser) { // weigh-ins of the selected user only
dataRows.innerHTML = "";
for (var i = 0, j = selUserData.length; i < j; i++) {
var dataDate = selUserData[i].date;
var dataWeight = selUserData[i].weight;
chartData.push('{ "User"' + ': ' + '"'+selUser+'", ' + '"Date":' + ' ' + '"'+dataDate+'", ' + '"Weight":' + ' ' + '"'+dataWeight+'" }');
// SNIP: build rows from the data, load up the table, no problem
dataRows.innerHTML += row;
} // selUserData loop
var svg = dimple.newSvg("#chartContainer", 800, 600);
var chart = new dimple.chart(svg, chartData);
chart.setBounds(60, 30, 505, 305);
var x = chart.addCategoryAxis("x", "Date");
x.addOrderRule("Dates");
var y = chart.addCategoryAxis("y", "Weight");
y.addOrderRule("Weights");
var s = chart.addSeries("weigh-ins", dimple.plot.line);
chart.draw();
... which results in a non-chart. However, if I console.log or alert(chartData) and set the result as chartData, i.e.:
var chartData = [
{ "User": "Wayne", "Date": "2016.02.01", "Weight": "180.3" },
{ "User": "Wayne", "Date": "2016.02.05", "Weight": "123.6" },
{ "User": "Wayne", "Date": "2016.02.06", "Weight": "153.9" }
]
... then I get a chart, ergo my confusion.
Any insight greatly appreciated,
Whiskey

You're pushing the JSON into your array as strings not objects, it should be:
chartData.push({ "User": selUser, "Date": dataDate, "Weight": dataWeight });
Which has the added benefit of being much easier to read!

Related

How to parse nested JSON in Javascript?

I am trying to parse and show JSON data (product catalog) using XMLHttpRequest method. I am able to display the brands and their names, but not able to showcase list of products progmatically.
Here is the sample JSON request:
{
"products": {
"laptop": [{
"brand": "sony",
"price": "$1000"
}, {
"brand": "acer",
"price": "$400"
}],
"cellphone": [{
"brand": "iphone",
"price": "$800"
}, {
"brand": "htc",
"price": "$500"
}],
"tablets": [{
"brand": "iPad",
"price": "$800"
}, {
"brand": "htc-tab",
"price": "$500"
}]
}
}
Right now I am using following code to show data in tabluar form:
function loadJSON() {
var data_file = "http://localhost/AJAX/productcatalog.json";
var http_request = new XMLHttpRequest();
http_request.onreadystatechange = function () {
if ((http_request.readyState == 4) && (http_request.status == 200)) {
// Javascript function JSON.parse to parse JSON data
var jsonObj = JSON.parse(http_request.responseText);
data = '<table border="2"><tr><td>Type</td><td>Brand</td><td>Price</td></tr>';
var i = 0;
debugger;
for (i = 0; i < jsonObj["products"].laptop.length; i++)
{
obj = jsonObj["products"].laptop[i];
data = data + '<tr><td>laptop</td><td>' + obj.brand + '</td><td>' + obj.price + '</td></tr>';
}
for (i = 0; i < jsonObj["products"].cellphone.length; i++)
{
obj = jsonObj["products"].cellphone[i];
data = data + '<tr><td>laptop</td><td>' + obj.brand + '</td><td>' + obj.price + '</td></tr>';
}
for (i = 0; i < jsonObj["products"].tablets.length; i++)
{
obj = jsonObj["products"].tablets[i];
data = data + '<tr><td>laptop</td><td>' + obj.brand + '</td><td>' + obj.price + '</td></tr>';
}
data += '</table>';
document.getElementById("demo").innerHTML = data;
}
}
http_request.open("GET", data_file, true);
http_request.send();
}
Question What is the way to fetch product list , i.e. products, cellphone and tablets ? Right now I have hardcoded that in order to fetch complete list of brands. Please advice. (I want to use plain javascript and not jquery)
Thanks!
It sounds like what you're missing is the "How do I iterate over an object when I don't know all the keys".
An object is a set of key, value pairs. You can use for/in syntax: for( var <key> in <object> ){} to get each key.
For your use case it might be something like:
var products = jsonObject['products'];
for( var productName in products ){
//productName would be "laptop", "cellphone", etc.
//products[productName] would be an array of brand/price objects
var product = products[productName];
for( var i=0; i<product.length; i++ ){
//product[i].brand
//product[i].price
}
}
In practice, I might use something a little less verbose, but this makes it easier to understand what is going on.
To achieve the expected i have used for loop and HTML DOM createElement() Method
var product_catalog = {
"products": {
"laptop": [{
"brand": "sony",
"price": "$1000"
}, {
"brand": "acer",
"price": "$400"
}],
"cellphone": [{
"brand": "iphone",
"price": "$800"
}, {
"brand": "htc",
"price": "$500"
}],
"tablets": [{
"brand": "iPad",
"price": "$800"
}, {
"brand": "htc-tab",
"price": "$500"
}]
}
};
var output = document.querySelector('#product tbody');
function build(JSONObject) {
/**get all keys***/
var keys = Object.keys(JSONObject);
/**get all subkeys***/
var subkeys = Object.keys(JSONObject[keys]);
console.log(subkeys);
/**loop sub keys to build HTML***/
for (var i = 0, tr, td; i < subkeys.length; i++) {
tr = document.createElement('tr');
td = document.createElement('td');
td.appendChild(document.createTextNode(subkeys[i]));
tr.appendChild(td);
output.appendChild(tr);
}
};
build(product_catalog);
HTML:
Coepen URL for reference- http://codepen.io/nagasai/pen/xOOqMv
Hope this works for you :)
Look at this example:
var x = data.key1.children.key4;
var path = "data";
function search(path, obj, target) {
for (var k in obj) {
if (obj.hasOwnProperty(k))
if (obj[k] === target)
return path + "['" + k + "']"
else if (typeof obj[k] === "object") {
var result = search(path + "['" + k + "']", obj[k], target);
if (result)
return result;
}
}
return false;
}
//Then for evry node that you need you can call the search() function.
var path = search(path, data, x);
console.log(path); //data['key1']['children']['key4']
I think this is what you're asking about, you can use Object.keys to get the properties of an object, then loop through them afterward.
var data = {
"products": {
"laptop": [{
"brand": "sony",
"price": "$1000"
}, {
"brand": "acer",
"price": "$400"
}],
"cellphone": [{
"brand": "iphone",
"price": "$800"
}, {
"brand": "htc",
"price": "$500"
}],
"tablets": [{
"brand": "iPad",
"price": "$800"
}, {
"brand": "htc-tab",
"price": "$500"
}]
}
}
var typesOfProducts = Object.keys(data.products)
console.log(typesOfProducts)
document.getElementById('output').textContent = typesOfProducts.toString()
//Then, to loop through
var i = -1,
len = typesOfProducts.length
function handleProduct(productType) {
console.log("This is the " + productType + " data.")
console.log(data.products[productType])
}
while (++i < len) {
handleProduct(typesOfProducts[i])
}
<div id="output"></div>
It sounds like what you're looking for is just an array of the keys of the "products" object. Example:
Products: ["laptop", "cellphone", "tablets"];
If so, I would just run your json object through javascript's Object.keys() method.
var jsonObj = JSON.parse(http_request.responseText);
var products = Object.keys(jsonObj.products);
// products = ["laptop", "cellphone", "tablets"];

Create an object with custom structure in javascript

I need to create an array object with this exact structure:
{"item1": {
0 : {
color:"description1",
width:"description2",
height:"description3"
}
1 : {
color:"description1",
width:"description2",
height:"description3"
}
//and so on
},
"item2": {
0 : {
color:"description1",
width:"description2",
height:"description3"
}
//and so on
}
//and so on
}
Estatically works fine. Now, I want to make it dinamically. So, the main question is... How can I loop the data while constructing the object at the same time?
This is an example of the incoming object I work from:
[
{
"uid": 1,
"legendname": "item1",
"rows": [
{
"uid": 0,
"color": "482400",
"width": "482400",
"height": "25"
},
{
"uid": 1,
"color": "587898",
"width": "789658",
"height": "30"
}
]
}
{
"uid": 2,
"legendname": "item2",
"rows": [
{
"uid": 0,
"color": "482400",
"width": "482400",
"height": "25"
}
]
}
]
How can I loop the data while constructing the object at the same time?
Is not clear. But if you want to create a new structure based on the incoming one, you can use this:
// ar = your incoming object
// b_obj = your result
var b_obj = {}
for (var i = 0; i < ar.length; i++)
{
item = ar[i];
b_item = {};
for (var i_row = 0; i_row < item.rows.length; i_row++)
{
var row = {};
row.color = item.rows[i_row].color;
row.width = item.rows[i_row].width;
row.height = item.rows[i_row].height;
b_item[i_row] = row;
}
b_obj[item.legendname] = b_item;
}

converting format of JSON

I am using an AJAX query to Fuseki, that I want to visualize in a D3.js collapsable tree. However Fuseki returns the JSON in a format that the D3.js code does not recognise. like this:
{
"head": {
"vars": [ "s" ]
} ,
"results": {
"bindings": [
{
"s": {
"type": "uri",
"value": "http://www.co-ode.org/ontologies/pizza/2005/05/16/pizza.owl#FourCheesesTopping"
},
"p": {
"type": "uri",
"value": "http://www.w3.org/2000/01/rdf-schema#subClassOf"
},
"o": {
"type": "uri",
"value": "http://www.co-ode.org/ontologies/pizza/2005/05/16/pizza.owl#CheeseTopping"
}
]
}
}
I need to convert this JSON into this format:
{
"name": "Pizza",
"children": [
{
"name": "http://www.co-ode.org/ontologies/pizza/2005/05/16/pizza.owl#PizzaBase",
"children": [
]
},
{
"name": "http://www.co-ode.org/ontologies/pizza/2005/05/16/pizza.owl#PizzaTopping",
"children": [
{
"name": "http://www.co-ode.org/ontologies/pizza/2005/05/16/pizza.owl#MeatTopping",
"children": [
{
"name": "http://www.co-ode.org/ontologies/pizza/2005/05/16/pizza.owl#HotSpicedBeefTopping"
}
]
}
]
}
]
}
I have tried taking the JSON and putting it into a new object with the correct format, but it is not working. Here is my code:
var parent = new Object();
var childArray=[];
var child = [];
function createChildObj(_children, children, depth, id, childName, parent, x, x0, y, y0){
var childObj = new Object();
childObj._children = _children;
childObj.children = children;
childObj.depth = depth;
childObj.id =id;
childObj.name = childName;
childObj.parent= parent;
childObj.x = x;
childObj.x0 = x0;
childObj.y = y;
childObj.y0 = y0;
return childObj;
};
console.log(root.length)
for (var i=0; i<root.length; i++){
var childName = root[i]["s"]["value"];
var childObj = createChildObj("children",null, 1, 2, childName, parent, 190, 190, 180, 180);
child.push(childObj);
}
parent.name = "Pizza";
parent.depth = 0;
parent.id = 3;
parent.children= child;
parent.x0 = root.x0;
parent.x = parent.x0;
parent.y0 = root.y0;
parent.y = parent.y0;
So I am aiming to have parent as the JSON object with the data in the correct format to parse to the d3. sorry its a mess, been fiddling for ages trying to learn D3, and the learning curve is steeper than I had anticipated. Any help would be great! cheers.

one of JSON values returns unidentified with JavaScript

I need to retrieve email field from JSON with JavaScript.
Here is the code:
"contacts": [
{
"addedAt": 1332358711001,
"vid": 1,
"properties": {
"lastname": {
"value": "Mott"
},
"firstname": {
"value": "Adrian"
}
},
"identity-profiles": [
{
"vid": 1,
"identities": [
{
"type": "EMAIL",
"value": "test-fdfc6c2e-e19e-4138-8201-8342ca333aa1#hubspot.com",
"timestamp": 1332358711715
},
{
"type": "LEAD_GUID",
"value": "f3ebaf07-1c6d-4ada-af31-3559dd8b3027",
"timestamp": 1332358711771
}
]
}
]
}]
The code works with all fields, except when I get to Identities, it returns NULL or unidentified.
var temp = fields.contacts.length;
for (var i=0; i<fields.contacts.length; i++){
var addedAt = fields.contacts[i].addedAt;
var formattedDate = Utilities.formatDate(new Date(addedAt), "GMT", "yyyy-MM-dd");
var lastName = fields.contacts[i].properties.lastname.value;
var firstName = fields.contacts[i].properties.firstname.value;
var vid = fields.contacts[i].vid;
var ip = fields.contacts[i]['identity-profiles'];
var id = ip.identities;
}
var id always returns unidentified. Also doesn't work:
for (var j=0; i<id.length; j++){
if(typeof ['type'] == 'EMAIL'){
var email = id[j].value;
}
};
fields.contacts[i]['identity-profiles'] is an array, it doesn't directly have a identities property.
You may want
var id = ip[0].identities;
or you should iterate over fields.contacts[i]['identity-profiles'] but it's not clear what you precisely want.

Why is JSON outputting out of order?

I'm am trying to get a list of weather information for 8 locations. I'm using a weather API that accepts longitude and latitude and spits back json output with the weather info for that location. I feed the coords in order 0->7 but when json processes the data it comes back in a seemingly random order. I assume it's because some process faster than others and json is outputing what it gets back as it gets it. The output is correct, only the order is wrong.
var loc = null;
var body = "";
var campuses = new Array(8);
campuses[0] = "34.47242,-84.42489,1";
campuses[1] = "33.81488,-84.62048,2";
campuses[2] = "34.27502,-84.46976,3";
campuses[3] = "33.92987,-84.55065,4";
campuses[4] = "34.03433,-84.46723,5";
campuses[5] = "34.08362,-84.67115,6";
campuses[6] = "33.91124,-84.82634,7";
campuses[7] = "34.10409,-84.51804,8";
function getWeather(campusArray)
{
body += '<p class="topTitle">Campus Weather</p>';
var cSplit = new Array();
cSplit = campusArray.split(',');
var loc = "http://www.worldweatheronline.com/feed/weather.ashx?q="+cSplit[0]+","+cSplit[1]+"&format=json&num_of_days=2&key=0a05fff921162948110401&callback=?";
$('#content').html('asdf');
$.getJSON(loc,function(js)
{
var data = js.data;
var humidity = data.current_condition[0].humidity;
var tempF = data.current_condition[0].temp_F;
var iconDESC = data.current_condition[0].weatherDesc[0].value;
var iconURL = data.current_condition[0].weatherIconUrl[0].value;
var windDir = data.current_condition[0].winddir16Point;
var windSpeed = data.current_condition[0].windspeedMiles;
var tempMaxF = data.weather[0].tempMaxF;
var tempMinF = data.weather[0].tempMinF;
body += '<p class="title">'+cSplit[2]+'</p>'+
'<span class="body">'+tempF+
' '+windSpeed+
'<img src="'+iconURL+'" /></span>';
$('#content').html(body);
});
}
getWeather(campuses[0]);
getWeather(campuses[1]);
getWeather(campuses[2]);
getWeather(campuses[3]);
getWeather(campuses[4]);
getWeather(campuses[5]);
getWeather(campuses[6]);
getWeather(campuses[7]);
I have also tried it as $.ajax
var loc = null;
var body = "";
var campuses = new Array(8);
campuses[0] = "34.47242,-84.42489,1";
campuses[1] = "33.81488,-84.62048,2";
campuses[2] = "34.27502,-84.46976,3";
campuses[3] = "33.92987,-84.55065,4";
campuses[4] = "34.03433,-84.46723,5";
campuses[5] = "34.08362,-84.67115,6";
campuses[6] = "33.91124,-84.82634,7";
campuses[7] = "34.10409,-84.51804,8";
function getWeather(campusArray)
{
body += '<p class="topTitle">Campus Weather</p>';
var cSplit = new Array();
cSplit = campusArray.split(',');
var loc = "http://www.worldweatheronline.com/feed/weather.ashx?q="+cSplit[0]+","+cSplit[1]+"&format=json&num_of_days=2&key=0a05fff921162948110401&callback=?";
$.ajax({
url: loc,
async: true,
dataType: "json",
success: function(js)
{
var data = js.data;
var humidity = data.current_condition[0].humidity;
var tempF = data.current_condition[0].temp_F;
var iconDESC = data.current_condition[0].weatherDesc[0].value;
var iconURL = data.current_condition[0].weatherIconUrl[0].value;
var windDir = data.current_condition[0].winddir16Point;
var windSpeed = data.current_condition[0].windspeedMiles;
var tempMaxF = data.weather[0].tempMaxF;
var tempMinF = data.weather[0].tempMinF;
body += '<p class="title">'+cSplit[2]+'</p>'+
'<span class="body">'+tempF+
' '+windSpeed+
'<img src="'+iconURL+'" /></span>';
$('#content').html(body);
}
});
}
getWeather(campuses[0]);
getWeather(campuses[1]);
getWeather(campuses[2]);
getWeather(campuses[3]);
getWeather(campuses[4]);
getWeather(campuses[5]);
getWeather(campuses[6]);
getWeather(campuses[7]);
EDIT:
example of json output:
{ "data": { "current_condition": [ {"cloudcover": "100", "humidity": "93", "observation_time": "04:04 PM", "precipMM": "0.0", "pressure": "1009", "temp_C": "2", "temp_F": "36", "visibility": "8", "weatherCode": "116", "weatherDesc": [ {"value": "Mist" } ], "weatherIconUrl": [ {"value": "http:\/\/www.worldweatheronline.com\/images\/wsymbols01_png_64\/wsymbol_0006_mist.png" } ], "winddir16Point": "WNW", "winddirDegree": "290", "windspeedKmph": "7", "windspeedMiles": "4" } ], "request": [ {"query": "Lat 34.47 and Lon -84.42", "type": "LatLon" } ], "weather": [ {"date": "2011-01-06", "precipMM": "9.3", "tempMaxC": "7", "tempMaxF": "45", "tempMinC": "2", "tempMinF": "35", "weatherCode": "113", "weatherDesc": [ {"value": "Sunny" } ], "weatherIconUrl": [ {"value": "http:\/\/www.worldweatheronline.com\/images\/wsymbols01_png_64\/wsymbol_0001_sunny.png" } ], "winddir16Point": "WNW", "winddirDegree": "293", "winddirection": "WNW", "windspeedKmph": "20", "windspeedMiles": "13" }, {"date": "2011-01-07", "precipMM": "0.0", "tempMaxC": "6", "tempMaxF": "44", "tempMinC": "0", "tempMinF": "31", "weatherCode": "116", "weatherDesc": [ {"value": "Partly Cloudy" } ], "weatherIconUrl": [ {"value": "http:\/\/www.worldweatheronline.com\/images\/wsymbols01_png_64\/wsymbol_0002_sunny_intervals.png" } ], "winddir16Point": "WNW", "winddirDegree": "286", "winddirection": "WNW", "windspeedKmph": "25", "windspeedMiles": "16" } ] }}
You need to modify the getJSON callback you are using to be recursive:
var loc = null, body = "", var campuses = [
"34.10409,-84.51804,8", "33.91124,-84.82634,7", "34.08362,-84.67115,6",
"34.03433,-84.46723,5", "33.92987,-84.55065,4", "34.27502,-84.46976,3",
"33.81488,-84.62048,2", "34.47242,-84.42489,1"
]; // notice they are sorted backwards
function getWeather(campusArray) {
var cSplit = [], loc;
body += '<p class="topTitle">Campus Weather</p>';
cSplit = campusArray.pop().split(','); // popping the array removes it
// from the length
/* truncated for brevity. Put your additional code here. */
$.getJSON(loc, function(js) {
/* truncated for brevity. Put your code here. */
if (campusArray.length) {
getWeather(campusArray);
}
});
}
getWeather(campuses);
You could use the Ajax method and specify async: false, which would cause each call to block. The alternative would be to have placeholders for each campus result and to replace that for each as the results are returned, you'd need to extend your getWeather method to accept the target element but that would mean you could still use the async Ajax approach which would be better for your users.

Categories