Why can't I access JS object properties? - javascript

I have the following function:
function getAggregateData(){
var sums = new Object();
$.getJSON("example.json.php", function(data) {
//for each month
c = 0;
$.each(data, function(key, val, index) {
//for each store
$.each(val, function(key2, val2, index2) {
if(c == 0){
sums[key2] = val2;
}
else{
sums[key2] += val2;
}
});
c++
});
})
return sums;
}
Which I then call as such:
var totals = getAggregateData();
But when I console log I am totally stumped:
console.log(totals)
reveals an object like this:
store1 500
store2 900
store3 750
and so on and so forth...
but when I do console.log(totals['store1') I get undefinded.
I have also tried console.log(totals.store1)
and console.log(totals[0].store1)
I am having some type of issue of scope, or I am not creating the object I think I am.

It looks like the function would be returning an empty object since it's not waiting for the AJAX call to finish.
If you tried doing console.log(totals.store1) on the last line inside your $.getJSON callback you'll probably get a result.
You'll need to put any code that requires data from "example.json.php" inside a callback that only gets run after the AJAX call has returned.
E.g.
function getAggregateData(){
var sums = new Object();
$.getJSON("example.json.php", function(data) {
//for each month
c = 0;
$.each(data, function(key, val, index) {
//for each store
$.each(val, function(key2, val2, index2) {
if(c == 0){
sums[key2] = val2;
}
else{
sums[key2] += val2;
}
});
c++
});
processAggregateData(sums);
})
}
function processAggregateData(totals) {
console.log(totals.store1);
}
getAggregateData();

given:
{
"1": {
"store1": 2450,
"store2": 1060,
"store3": 310
},
"2": {
"store1": 2460,
"store2": 1760,
"store3": 810
}
};
This should work if you intend to add the results for each store.
/**
* This functions need to be called when we have the data
*/
function processSums(obj){
console.log(obj);
}
function getAggregateData(){
var sums = {};
$.getJSON("example.json.php", function(data) {
$.each(data, function() {
$.each(this, function(key, val, index){
sums[key] = sums[key] || 0;
sums[key] += val;
});
});
// 4910
processSums(sums);
});
return sums;
}
getAggregateData();

Related

Get values from JSON file and sort by key number value

I was wondering if someone could help me get this to work so it prints out values and sorts them by propertyCount, highest to lowest. Below gets me the the first 6 values from a JSON file.
Basically, Im trying to only grab 6 values from a JSON file where it's sorted by a key called count that has a number value. Any help is greatly appreciated.
var countyInfo = [];
var count = 0;
var propertyCount = 0;
function getCountyInfo($j) {
//$j.ajax({
// url: "/info.json?st=WA"
//}).done(function(data) {
//countyInfo = data;
countyInfo = getDataDemo();
$j.each(countyInfo.counts.county_info, function(key, value) {
$j.each(value, function(key, value) {
if (key == "count") {
propertyCount = value;
}
if (key == "countyName" && value != null) {
var countyName = value;
if (count < 6) {
$j('#countyList').append('<li class="topCountyRow">' + countyName + ' (' + propertyCount + ')</li>');
}
count++;
}
});
});
//});
}
(function($j) {
//loaded();
var county_info = [];
getCountyInfo($j);
})(jQuery);
// Just for the StackOverflow Question
function getDataDemo() {
return JSON.parse(`{
"state": "wa",
"stateName": "Washington",
"counts": {
"county_info": [
{
"count": 72,
"countyName": "Anderson"
},
{
"count": 43,
"countyName": "Angelina"
}
]
}
}`);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ul id="countyList" class="ulTwoColumns"></ul>
You can use sort function of array where you need to pass comparer function as below.
function sort(data)
{
return data.counts.county_info.sort((left,right)=>{
return left.count<right.count?1:-1;
})
}
Updated as per your data.
Use the sort method to compare and sort
data.counts.county_info.sort(a, b => a.count < b.count);
Implementing in your code above
function getCountyInfo(){
$j.ajax({
url: "/info.json?st=WA"
}).done(function(data) {
let sortedData = data.counts.county_info.sort(a, b => a.count < b.count);
// other things to do
});
}

show nested json data in treeview in javascript

i have nested json data. i used the blow function.
var jsonSource={"error_code":0, "ext_info":{"name":{"firstName":"John","lastName":"Jonson","nickName":"JJ"}}};
var obj=JSON.parse(jsonSource),returnValue;
function showJson(obj){
for(var key in obj){
if(typeof obj[key]==='object'){
returnValue+='<div>'+key+'/\n';
showJson(obj[key]);
returnValue+='</div>';
} else{
returnValue+=key+'equal'+obj[key];
}
}
docoument.getElementById('data').innerHTML=returnValue;
}
as i said before , i have a large nested json data and when i parse it to showJson function ,it just shows one level of json data and puts others deep level of dataJson undefined.
what should i do to resolve the problem?
Recursive approach works more intuitively when done with actual return values. Have a look at https://jsfiddle.net/ughnjfh0/1/
var jsonSource='{"error_code":0, "ext_info":{"name":{"firstName":"John","lastName":"Jonson","nickName":"JJ"}}}';
var obj=JSON.parse(jsonSource);
function showJson(obj){
var returnValue='';
for(var key in obj){
if(typeof obj[key]==='object'){
returnValue+='<div>'+key+'/\n';
returnValue+=showJson(obj[key]);
returnValue+='</div>';
} else{
returnValue+=key+'equal'+obj[key];
}
}
return returnValue;
}
document.getElementById('data').innerHTML= showJson(obj);
Also:
jsonSource should be a string to be properly parsable as JSON data
typo in docoument.getElementById('data').innerHTML=returnValue;
Some of your problems:
jsonSource is already an object
you try to assign the returnValue in every call of showJson
Better to use a clean approach for looping and returning of the items:
var obj = { "error_code": 0, "ext_info": { "name": { "firstName": "John", "lastName": "Jonson", "nickName": "JJ" } } };
function showObj(obj) {
return Object.keys(obj).map(function (k) {
if (typeof obj[k] === 'object') {
return k + ':<br><div style="margin-left: 25px;">' + showObj(obj[k]) + '</div>';
}
return k + ': ' + obj[k];
}).join('<br>');
}
document.getElementById('data').innerHTML = showObj(obj);
<div id="data"></div>
// obj is the object to loop, ul is the ul to append lis to
function loop(obj, ul) {
$.each(obj, function(key, val) {
if(val && typeof val === "object") { // object, call recursively
var ul2 = $("<ul>").appendTo(
$("<li>").appendTo(ul)
);
loop(val, ul2);
} else {
$("<li>").text(val).appendTo(ul);
}
});
}
var ul = $("<ul>");
var jsonSource={"error_code":0, "ext_info":{"name":{"firstName":"John","lastName":"Jonson","nickName":"JJ"}}};
var data=JSON.parse(jsonSource)
loop(data, ul);
ul.addClass("my-new-list").appendTo('body');

get specific text from value with javascript

I have a json.json file like this
{
"name1":"ts1=Hallo&ts2=Hillarry&ts3=Sting&ts4=Storm",
"name2":"st1=Hallo2&st2=Hillarry2&st3=Sting2&st4=Storm2",
"name3":"dr1=Hallo3&dr2=Hillarry3&dr3=Sting3&dr4=Storm3",
"name4":"ds1=Hallo4&ds2=Hillarry4&ds3=Sting4&ds4=Storm4"
}
And this script im using to read the file
<script type='text/javascript'>
$(window).load(function(){
$.getJSON("json.json", function(person){
document.write(person.name3);
});
});
</script>
This script is made to point out all of the data from "name3" but i need only "dr3" value from "name3" to be stored to be written.
How to do that?
You can store it like this using combination of split() calls.
var dr3val = person.name3.split("&")[2].split("=")[1];
console.log(dr3val); // "Sting3"
The above will work if the order is same. Else you can use the below
var dr3val = person.name3.replace(/.*?dr3=(.+)?&.*/,"$1");
console.log(dr3val); // "Sting3"
You should change your json to this:
{
"name1":
{
"ts1" : "Hallo",
"ts2" : "Hillarry",
"ts3" : "Sting",
"ts4" : "Storm"
}
}
this way it makes your jsonstring much easier to use.
Get the data from it like this:
person.name1.ts1
var json = {
"name1":"ts1=Hallo&ts2=Hillarry&ts3=Sting&ts4=Storm",
"name2":"st1=Hallo2&st2=Hillarry2&st3=Sting2&st4=Storm2",
"name3":"dr1=Hallo3&dr2=Hillarry3&dr3=Sting3&dr4=Storm3",
"name4":"ds1=Hallo4&ds2=Hillarry4&ds3=Sting4&ds4=Storm4"
};
var name3 = json.name3.split('&');
for (var i = 0; i < name3.length; i++) {
if (name3[i].indexOf("dr3=") > -1) {
var value = name3[i].replace("dr3=", "");
alert(value);
}
}
Implement this jQuery plugin i made for a similar case i had to solve some time ago. This plugin has the benefit that it handles multiple occurring variables and gathers them within an array, simulating a webserver behaviour.
<script type='text/javascript'>
(function($) {
$.StringParams = function(string) {
if (string == "") return {};
var result = {},
matches = string.split('&');
for(var i = 0, pair, key, value; i < matches.length; i++) {
pair = matches[i].split('=');
key = pair[0];
if(pair.length == 2) {
value = decodeURIComponent(pair[1].replace(/\+/g, " "));
} else {
value = null;
}
switch($.type(result[key])) {
case 'undefined':
result[key] = value;
break;
case 'array':
result[key].push(value);
break;
default:
result[key] = [result[key], value];
}
}
return result;
}
})(jQuery);
</script>
Then in your code do:
<script type='text/javascript'>
$(window).load(function(){
var attributes3;
$.getJSON("json.json", function(person){
attributes3 = $.StringParams(person.name3)
console.log(attributes3.dr3);
});
});
</script>
Underscore solution:
_.map(json, function(query) { //map the value of each property in json object
return _.object( //to an object created from array
query.split('&') //resulting from splitting the query at &
.map(function(keyval) { //and turning each of the key=value parts
return keyval.split('='); //into a 2-element array split at the equals.
);
})
The result of the query.split... part is
[ [ 'ts1', 'Hallo'], ['ts2', 'Hillarry'], ... ]
Underscore's _.object function turns that into
{ ts1: 'Hallo', ts2: 'Hillarry', ... }
The end result is
{
name1: { ts1: 'hHallo', ts2: 'Hillarry, ...},
name2: { ...
}
Now result can be obtained with object.name3.dr3.
Avoiding Underscore
However, if you hate Underscore or don't want to use it, what it's doing with _.map and _.object is not hard to replicate, and could be a useful learning exercise. Both use the useful Array#reduce function.
function object_map(object, fn) {
return Object.keys(object).reduce(function(result, key) {
result[key] = fn(object[key]);
return result;
}, {});
}
function object_from_keyvals(keyvals) {
return keyvals.reduce(function(result, v) {
result[v[0]] = v[1];
return result;
}, {});
}
:
var person={
"name1":"ts1=Hallo&ts2=Hillarry&ts3=Sting&ts4=Storm",
"name2":"st1=Hallo2&st2=Hillarry2&st3=Sting2&st4=Storm2",
"name3":"dr1=Hallo3&dr2=Hillarry3&dr3=Sting3&dr4=Storm3",
"name4":"ds1=Hallo4&ds2=Hillarry4&ds3=Sting4&ds4=Storm4"
}
var pN = person.name3;
var toSearch = 'dr3';
var ar = pN.split('&');
var result = '';
for(var i=0; i< ar.length; i++)
if(ar[i].indexOf(toSearch) >= 0 )
result=ar[i].split('=')[1];
console.log('result=='+result);

encapsulation issue with making an array of objects

Would anyone mind explaining to me why...
$(document).ready(function() {
var scu = ['0291285', '0409338', '0521704', '0521990', '0523652', '0523657', '0523660', '0523704'];
var inData = $('#output');
var testdiv = $('#testdiv');
function Item(scu, description, price, extended, type) {
this.scu = scu;
this.description = description;
this.price = price;
this.extended = extended;
this.type = type;
//this.saved = function() {};
}
var rows = [];
function get() {
inData.html('');
$.each(scu, function(index, val) {
$.post('chBuild.php', {scu:val}, function(output) {
$.each(output, function(i, obj) {
var i = 0;
rows[i] = new Item(obj.scu, obj.description, obj.price, obj.extended, obj.type);
console.log(rows[i].price)
//this logs every object but...
i =+ 1;
});
}, 'json');
});
console.log(rows[0].price);
//this says rows[0] is undefined?
}
inData.click(get);
});
I am trying to find the best way to create and store multiple objects.
$.post('chBuild.php', {scu:val}, function(output) {
$.each(output, function(i, obj) {
var i = 0;
rows[i] = new Item(obj.scu, obj.description, obj.price, obj.extended, obj.type);
console.log(rows[i].price)
i =+ 1;
});
}, 'json');
Here the call to $.post is asynchronous, is going to be filled just when the ajax call returns. Maybe you should make it synchronous
$.ajax({'url': 'chBuild.php', 'async': false, ...);
It's because $.post is asynchronous. The each only start the HTTP request, but it returns immediatly, so when the second console.log runs the item had not been created yet.

Return a value with jQuery each() function

i'm new to javascript, and I would like to retrieve values from JSON and push it into an array so that I can parse again this array in another function, But I don't know how to return the array after pushing element inside it.
In the following script I can't display values in items
function gC(b,c,p) {
$.getJSON('getmonths', 'b='+b+'&c='+c+'&p='+p, processJSON);
}
function processJSON(data) {
var retval = [];
$.each(data, function(key, val) {
retval.push(val);
//alert(retval.pop());
});
return retval;
}
$(document).ready(function(){
var b = $("#b").val();
var c = $("#c").val();
var p = $("#p").val();
var items = [];
items = gC(b,c,p);
var i = 0;
$('td').each(function(index) {
$(this).attr('bgcolor', items[i]);
i++;
}
How could I access the array ?
thank !
You don't return from an AJAX call, you have it call a callback function when it's done.
function gC(b,c,p) {
var retval = [];
$.getJSON('getmonths', 'b='+b+'&c='+c+'&p='+p, processData);
}
function processData(data){
var retval = [];
$.each(data, function(key, val) {
retval.push(val);
//alert(retval.pop());
});
alert(retval);
}
processData would be called when the AJAX call is done. This can't return a value to another function, so all your logic has to be inside this callback function.
UPDATE: You can also pass in a callback function to gC to be called when it's done.
function gC(b,c,p,f) {
var retval = [];
$.getJSON('getmonths', 'b='+b+'&c='+c+'&p='+p, function(d){
if(typeof f == 'function'){
f(d);
}
});
}
Then you call gC like so:
gC(b,c,p,function(data){
var retval = [];
$.each(data, function(key, val) {
retval.push(val);
//alert(retval.pop());
});
alert(retval);
});
UPDATE2: I saw the code you added to the question. This needs to be done in the callback.
gC(b,c,p,function(data){
var items = [];
$.each(data, function(key, val) {
items.push(val);
});
$('td').each(function(index){ // You don't need a separate i variable
// you can just use the index from the loop
$(this).attr('bgcolor', items[index]);
}
})
Just have the code inside the callback:
function processJSON(data) {
var retval = [];
$.each(data, function(key, val) {
retval.push(val);
});
$('td').each(function(index) {
if (index < retval.length)
$(this).attr('bgcolor', retval[index]);
});
}

Categories

Resources