access nested json data from ajax call - javascript

I am interfacing with an API which returns JSON data to me. As the results are not stored in a file, but rather server memory, I am having a hard time figuring out how to access the data and write it to my html webpage. Here's what my $.ajax call looks like:
$.ajax({
type: "post",
url:"https://www.xxx/v1/trips/search? key=xxxx",
data:JSON.stringify({request : requestTrav1Dest1}),
dataType:"json",
success:successFunction,
headers:{"Content-Type":"application/json"}
});
Here's what the JSON I get back from the server looks like:
{
"kind": "#tripsSearch",
"trips": {
"kind": "#tripOptions",
"tripOption": [
{
"saleTotal": "USD294.10",
"id": "DMfSXrkVQGKTVQsDD5l60N004",
},
"saleTotal": "USD333.10",
"id": "DMfSXrkVQGKTVQsDD5l60N002",
},
{
"saleTotal": "USD225.94",
"id": "DMfSXrkVQGKTVQsDD5l60N005",
}
]
}
}
What I really need is the saleTotal for each tripOption.
I broke out the function that runs if the query is a success here:
function successFunction(servResponse){
$('#content').load('resultsPage.html #content');
var newContent = '';
for(var i = 0; i < servResponse.trips.tripOption[i].length; i++){
newContent += '<div class="results">';
newContent += '<p>' + "Option " + (i+1) + '<br>';
newContent += servResponse.trips.tripOption[0].saleTotal + '<br>';
newContent += '</div>';
}
document.getElementById('content').innerhtml = newContent;
}
Unfortunately, this does not write out anything to the webpage. So far I can only view the raw JSON results in the Chrome Developer's Toolbar Console.
Can someone please help identify what I need to do differently?
Thanks in advance!

Assuming you have an element on the page with the ID of content, it should work fine, you just have a little typo
document.getElementById('content').innerhtml = newContent;
capitlize the 'HTML',
document.getElementById('content').innerHTML = newContent;
$('#content').load('resultsPage.html #content'); looks incorrect, the 1st parameter should just be a URL. Try commenting it out, for now, since you're changing it's content with the other line.

Also, the 4th line should be:
for(var i = 0; i < servResponse.trips.tripOption.length; i++){
You have:
... tripOption[i].length ...
The function below should:
Create one div with the class="results"
Place several p elements inside this div, each containing a 2-line entry
Display all this inside the element with an id of "content"
Is this what you want? The CSS that you are currently applying to .results may need to be applied to .results p instead.
function successFunction(servResponse){
var tripOption = servResponse.trips.tripOption;
var newContent = '<div class="results">';
for(var i = 0; i < tripOption.length; i++){
newContent += '<p>' + "Option " + (i+1) + '<br>';
newContent += tripOption[i].saleTotal + '<p>';
}
newContent += '</div>';
document.getElementById('content').innerHTML = newContent;
}
jsFiddle

var servResponse = {
"kind": "#tripsSearch",
"trips": {
"kind": "#tripOptions",
"tripOption": [
{
"saleTotal": "USD294.10",
"id": "DMfSXrkVQGKTVQsDD5l60N004",
},{
"saleTotal": "USD333.10",
"id": "DMfSXrkVQGKTVQsDD5l60N002",
},
{
"saleTotal": "USD225.94",
"id": "DMfSXrkVQGKTVQsDD5l60N005",
}
]
}
};
function successFunction(servResponse) {
var newContent = '';
servResponse.trips.tripOption.forEach(function(el,index){
newContent += '<div class="results">';
newContent += '<p>' + "Option " + (index+1) + '<br>';
newContent += el.saleTotal + '<br>';
newContent += '</div>';
console.log(el.saleTotal);
});
document.getElementById('content').innerHTML = newContent;
}
successFunction(servResponse);
Using pure javascript forEach loop
Example Link : http://jsfiddle.net/c1wzsqaf/1/

Related

alternating between even and odd elements in json with JS

I'm trying to generate a .html div containers using .json file that looks like below.
[
{
"KEYWORD": XXXX,
"DATEx": XXXX,
"TOPIC": XXXX,
"CSPANLINK": XXXX,
"EXCERPTS": XXXX
},
{
"KEYWORD": YYYY,
"DATEx": YYYY,
"TOPIC": YYYY,
"CSPANLINK": YYYY,
"EXCERPTS": YYYY
}]
For odd numbered elements, I want to create div with class = "container left" and for even numbered elements, I want to create div with class = "container right". I used the below code to generate .html:
$.getJSON("XXXXYYYY.json", function (data) {
var html = '';
$.each(data, function (key, value) {
html += '<div class="container left">';
html += '<div class="content">';
html += '<h2>' + value.DATEx + '</h2>'
html += '<p>' + value.EXCERPTS + '</p>';
html += '</div>';
html += '</div>';
});
$('div.timeline').html(html);
});
So in a nutshell, I would like to alternate between these two codes, depending on the index of each element.
html += '<div class="container left">';
and
html += '<div class="container right">';
What kind of javascript conditional statement should I use to do this?
The parameter you pass in the $.each is the array and the function callback with index and value
$.each([ 52, 97 ], function( index, value ) {
alert( index + ": " + value );
});
So in your case you can check even odd for your index and add the class accordingly.
Something like this
$.getJSON("XXXXYYYY.json", function (data) {
var html = '';
$.each(data, function (index, value) {
html += index%2===0 ? '<div class="container right">' : '<div class="container left">';
html += '<div class="content">';
html += '<h2>' + value.DATEx + '</h2>'
html += '<p>' + value.EXCERPTS + '</p>';
html += '</div>';
html += '</div>';
});
$('div.timeline').html(html);
});
looks like its an duplication of:
Is this an even or odd element?
Therefor the following Code should work for you.
$('div').each(function(i, el) {
// As a side note, this === el.
if (i % 2 === 0) { /* we are even */ }
else { /* we are odd */ }
});

print array of object in javascript and print in html tags

i am using storelocater.js for multiple location in google map and show the information according to the location with image. i can show only one image but i want to show multiple images inside the information panel. link this
Here is my code
var panelDiv = document.getElementById('panel');
storeLocator.Panel.NO_STORES_IN_VIEW_HTML_ = '<li class="no-stores">The nearest outlet:</li>';
var Store = storeLocator.Store;
Store.prototype.generateFieldsHTML_ = function(fields) {
var html = '';
html += '<div class="store-data">';
if(this.props_['title']){
html += '<div class="title"><div class="img-list clearfix">' +
for (var i = 0; i <= this.props_[images].length; i++) {
console.log(this.props_[images[i]]);
// <img src=' + this.props_['images'] + '>
}
+ '</div></div>'
}
html += '</div>';
return html;
}
var data = new storeLocator.StaticDataFeed;
data.setStores([
new storeLocator.Store('store02', new google.maps.LatLng(27.67663,85.31093), null, {images: ["img/thapathalil.jpg","img/thapathalil.jpg","img/thapathalil.jpg"]})
]);
and it shows:
Uncaught SyntaxError: Unexpected token for...
how can i solve this?? how can i fetch location inside of "images"
THANKS in advance
Actually you got Uncaught SyntaxError: Unexpected token for... because you used the for..loop in the string concatenation statement, directly after the + sign.
Change this code :
html += '<div class="title"><div class="img-list clearfix">' +
for (var i = 0; i <= this.props_[images].length; i++) {
console.log(this.props_[images[i]]);
// <img src=' + this.props_['images'] + '>
}
+ '</div></div>'
To the following:
html += '<div class="title"><div class="img-list clearfix">';
for (var i = 0; i <= this.props_['images'].length; i++) {
console.log(this.props_['images'][i]);
html += '<img src=' + this.props_['images'][i] + '>';
}
html += '</div></div>'
Note:
You should separate the concatenation of strings to the html
variable and the for loop logic, using html += instead of just using concatenation with + sign on multiple lines.
Make sure to wrap the properties names between two '' while accessing your objects, like in this.props_[images] where it should be this.props_['images'] and in this.props_[images[i]] where it should be this.props_['images'][i].
And the first 2 lines of your html variable decalaration and the concatenation, var html = ''; html += '<div class="store-data">'; can be shortened to just var html = '<div class="store-data">';.
I think there is a typo. Change this:
console.log(this.props_[images[i]])
to
console.log(this.props_['images'][i])
And you should use
i < this.props_['images'].length
So try this:
for (var i = 0; i < this.props_['images'].length; i++) {
console.log(this.props_['images'][i]);
}

How to return a variable from a callback after building variable with .getjson and .each

The Problem
I'm trying to figure out how to return HTML that I've built from a JSON file with jQuery.
I seem to have gotten returnLocations() to wait until getLocations() is finished so that the variable locationsBody is finalized with information gathered from my .each loop. The trouble (I think) is my not being able to return that variable to output it to my HTML page.
The Question
How can I return the variable locationsBody?
Note
(there may be errors in the below code as I trimmed it down as best I could but I think it should illustrate the problem with or without them)
The jQuery
the global variables
var locationsFull = 'un d fined';
var locationsOpener = '' +
'<div class="locations-header">places youve been</div>' +
'<div class="locations-container">' +
'<div class="locations-nav left">left</div>' +
'<div class="locations-nav right">right</div>'
;
var locationsBody = '<div class="locations-inner">'; // opening of container
var locationsCloser = '</div>'; // closing of container
the function
function locationsFunction() {
function getLocations() {
var wait = $.Deferred();
var area = 'Area1';
var counter = 1;
$.getJSON("locations.json", function(data) {
$(data.places).each(function() {
var location = this.location;
var image = this.image;
if (this.area === 'Area1') {
if (counter == 2) {
locationsBody = locationsBody +
'<div class="locations-places">' +
'<img src="images/places/' + image + '">' +
'<div class="locations-places-image">' + location + '</div>' +
'</div></div>'
;
counter = 0; // added closing of container, reset to 0
} else {
locationsBody = locationsBody +
'<div class="locations-places">' +
'<img src="images/places/' + image + '">' +
'<div class="locations-places-image">' + location + '</div>' +
'</div>'
;
counter = counter + 1;
}
}
})
wait.resolve();
})
return wait;
}
function returnLocations() {
locationsFull = locationsOpener + locationsBody + locationsCloser; // works, proven in alert and console.log
//alert(locationsFull); // works
console.log(locationsFull); // works
//return locationsFull; // doesnt work
//return 'anything'; // doesnt work
}
getLocations().then(returnLocations);
}
the call
$(function() {
$('.locations-body').html(locationsFunction());
})
The JSON File
{"places":[
{
"area": "Area1",
"location": "Downtown",
"image": "downtown.jpg"
},
{
"area": "Area1",
"location": "Uptown",
"image": "uptown.jpg"
}
]}
The HTML
<div class="locations-body"></div>
Further Note: Questions similar to this have been asked dozens of times on stackoverflow alone and those questions and answers have hundreds of thousands of reads. I have read through all of the top ones and more over the last 2 days. My problem is my inability to thoroughly understand the answers and apply them to my exact situation as seems to be the problem of the dozens (hundreds/thousands?) of people asking these questions and the hundreds of thousands (millions?) of people that have been searching for solutions to asynchronous problems.
You could just call .html() inside the returnLocations() function if that's viable.
the function
function returnLocations() {
locationsFull = locationsOpener + locationsBody + locationsCloser;
$('.locations-body').html(locationsFull);
}
the call
$(function() {
locationsFunction();
}
Otherwise you'll need to look into callbacks, read this, if you need to do it this way I can update my answer with an example later on.
Have you tried
return wait.promise();
instead of returning the Deferred?
Then calling like this:
var deferredChain = $.Deferred();
deferredChain.then(getLocations).then(returnLocations);
deferredChain.resolve();
I discovered today that simply putting a .done at the end of $.getJSON seems to work just the same and is much easier than using $.Deferred and the associated lines of code to make it work.
function locationsFunction() {
var area = 'Area1';
var counter = 1;
$.getJSON("locations.json", function(data) {
$(data.places).each(function() {
var location = this.location;
var image = this.image;
if (this.area === 'Area1') {
if (counter == 2) {
locationsBody = locationsBody +
'<div class="locations-places">' +
'<img src="images/places/' + image + '">' +
'<div class="locations-places-image">' + location + '</div>' +
'</div></div>'
;
counter = 0; // added closing of container, reset to 0
} else {
locationsBody = locationsBody +
'<div class="locations-places">' +
'<img src="images/places/' + image + '">' +
'<div class="locations-places-image">' + location + '</div>' +
'</div>'
;
counter = counter + 1;
}
}
})
}).done(function() {
locationsFull = locationsOpener + locationsBody + locationsCloser;
$('.locations-body').html(locationsFull);
});
}

Creating html elements through nested JSON objects

So I've managed to successfully create HTML elements through JSON objects before, but now that I've changed my JSON objects to nested JSON, I am not able to reproduce the HTML elements accordingly. I am pretty new to programming so can anyone help me find out where I have gone wrong?
JSON File:
{
"ThreeG": [
{
"title":"Testing 1",
"filePath":"https://example.com",
"imagePath":"images/test.jpg"
},
{
"title":"Testing 2",
"filePath":"https://example.com",
"imagePath":"images/test2.jpg"
}
]
}
Script:
<script>
$.ajax({
url : "TestFiles.json",
type : "post",
contentType:"application/json",
success : function(list){
var divCol = "<div class='col-md-offset-1 col-sm-5 col-md-5'>";
var divWell = "<div class='well' style='position:relative'>";
var divClose= "</div>";
list.forEach(function(obj, index) {
var title = "<h4>" + obj.ThreeG.title + "</h4>";
var linkStart = "<a href='" + obj.ThreeG.filePath + "' target='_blank'>" ;
var image = "<img data-toggle='tooltip' data-placement='left' title='Click to open data' src='" + obj.ThreeG.imagePath + "' height='100%' width='100%'/>"
var linkEnd = "</a>";
var div = divCol +
divWell +
title +
linkStart +
image +
linkEnd +
divClose +
divClose;
console.log(obj);
$("#test").append(div);
})
}
});
</script>
The list param in the success callback is an object with property / key ThreeG. So instead of list.forEach, you should do list.ThreeG.forEach, then each obj in the forEach callback will be the json object that you can use to create HTML elements.
list.ThreeG.forEach(function(obj, index) {
console.log(obj); // { "title":"Testing 1", "filePath":"https://example.com", "imagePath":"images/test.jpg" } for the first object
}
var obj = {
"ThreeG": [
{
"title":"Testing 1",
"filePath":"https://example.com",
"imagePath":"images/test.jpg"
},
{
"title":"Testing 2",
"filePath":"https://example.com",
"imagePath":"images/test2.jpg"
}
]
};
for(var i=0;i<obj.ThreeG.length;i++) {
var data = obj.ThreeG[i];//Take a reference here
console.log(data.title, data.filePath, data.imagePath);
}
You cannot say obj.ThreeG.title since obj.ThreeG is an array. You need to use obj.ThreeG[0].title and obj.ThreeG[1].title etc.
Do some looping as shown above.

Looping through json subobjects and doing something with each "element"

I am a newbie with json arrays/objects. I am trying to get to some subobjects within my .json file. I have tried the suggestions on here, but I keep getting "undefined" results. Here is the .json --
{
"DACcourses": [
{
"longTitle": "<a href='#'>Ammo-29 Electrical Explosives Safety for Naval Facilities</a>",
"longDescript": "ammo-29.html",
"atrrsLink": "Win 95+",
"delMeth": "standard",
"sked": [
{
"classNumb": "926",
"startDate": "4/16/2012",
"endDate": "4/20/2012",
"location": "NMC Fort Worth, TX",
"status": "scheduled",
"emptySeats": "Availability"
},
{
"classNumb": "001",
"startDate": "6/4/2012",
"endDate": "6/8/2012",
"location": "McAlester, OK",
"status": "scheduled",
"emptySeats": "Availability"
},
{
"classNumb": "920",
"startDate": "6/18/2012",
"endDate": "6/22/2012",
"location": "Belle Chasse, LA",
"status": "scheduled",
"emptySeats": "Class Full"
}
]}
]}
I must be doing something fundamentally wrong. so here is my code. In the end I am trying to build table rows out of each of the 'sked' objects. But I am having problems with getting individual data elements to show in the console. Here has been my attempts:
$('#content').on("click", "#catList tbody tr", function() {
var aData = oTable.fnGetData( this );
console.log( aData );
var scheduleData = aData.sked;
var catLink = 'catalog/' + aData.longDescript;
$('#fullDescript').load(catLink, function() {
if (!$('#fullDescript #offerings')) {
$('.enrollBTN').hide();
};
if ($(scheduleData).length > 0) {
$(scheduleData).each(function() {
for(var i = 0; i < scheduleData.length; i++) {
/*var startDate = aData.sked.startDate[2];
var endDate = aData.sked.endDate[3];
var location = aData.sked.location[4];
var classNumb = aData.sked.classNumb[1];
var status = aData.sked.status[5];
var emptySeats = aData.sked.emptySeats[6];*/
//var item = scheduleData[i];
console.log( aData.sked.startDate[2] );
var html = "<tr>";
html += "<td>" + item.classNumb + "<\/td>";
//console.log( aData.sked[1].classNumb );
/*html += "<td>" + scheduleData.endDate + "<\/td>";
html += "<td>" + scheduleData.location + "<\/td>";
html += "<td>" + scheduleData.classNumb + "<\/td>";
html += "<td>" + scheduleData.status + "<\/td>";
html += "<td>" + scheduleData.emptySeats + "<\/td>";*/
html += "<\/tr>";
//return scheduleData;
};
$('#schedule tbody').append($(html));
});
};
});
$('#content').hide();
$('#fullDescript').show();
});
Any help is appreciated.
It seems like you would only need the each or for loop, but not both. It also looks like there's some confusion in there on whether to use item = scheduleData[i] or not. Try this:
if ($(scheduleData).length > 0) {
for(var i = 0; i < scheduleData.length; i++) {
var item = scheduleData[i];
var html = "<tr>";
html += "<td>" + item.endDate + "</td>";
// ... etc
html += "</td>";
}
}
Just as a PS, I'd recommend looking into a JS templating tool like Mustache.js. This would allow you to separate data from display template, so you could eliminate the parsing code. It would look something like this:
var template = "{{#sked}}<tr><td>{{endDate}}</td><td>{{location}}</td></tr>{{/sked}}";
var html = "<table>" + Mustache.render(template, aData) + "</table>";
I must be doing something fundamentally wrong
Yes you are.
When you use .each loop, you refer to the current element by this keyword. So you do not need the for loop. Or, if you want the for loop, you do not need the .each loop. In my opinion, use the for loop. .each is just an overhead in this case.
UPDATE: #dbaseman gave you exactly what you need :)
UPDATE 2: Please try the following code. Basically its same as that of dbaseman, but dbaseman's snippet missed closing the <tr> element.
if ($(scheduleData).length > 0) {
for(var i = 0; i < scheduleData.length; i++) {
var item = scheduleData[i];
var html = "<tr>";
html += "<td>" + item.endDate + "</td>";
// ... etc
html += "</tr>"; // should close the <tr> here
}
}

Categories