Fetch all data from json and display it on the index page - javascript

I have the following json:
[
{
"countryId" : 0,
"countryImg" : "../img/france.jpg",
"countryName" : "France",
"countryInfo" : {
"headOfState" : "Francois Hollande",
"capital" : "Paris",
"population" : 66660000,
"area" : 643801,
"language" : "French"
},
"largestCities" : [
{"Paris" : "../img/paris.jpg"},
{"Marseille" : "../img/marseille.jpg"},
{"Lyon" : "../img/lyon.jpg"}
]
},
{
"countryId" : 1,
"countryImg" : "../img/germany.jpg",
"countryName" : "Germany",
"countryInfo" : {
"headOfState" : "Angela Merkel",
"capital" : "Berlin",
"population" : 81459000,
"area" : 357168,
"language" : "German"
},
"largestCities" : [
{"Berlin" : "../img/berlin.jpg"},
{"Munich" : "../img/munich.jpg"},
{"Hamburg" : "../img/hamburg.jpg"}
]
}
]
I need put it in my index.html, however I don't understand why I get only the second object? I need to put two objects in index. Maybe I need to use a loop? How do I do this properly?
I have the following javascript code:
$.ajax({
method: "POST",
url: "../data/data.json"
}).done(function (data) {
/*console.log(data);*/
localStorage.setItem('jsonData', JSON.stringify(data));
var dataFromLocStor = localStorage.getItem('jsonData');
var dataObject = JSON.parse(dataFromLocStor);
console.log(dataObject);
function Countries(){
this.getCountries = function () {
var ulListElem = document.getElementById("list-of-teams").children,
imgCountry = document.createElement('img');
for(country in dataObject){
/*console.log(dataObject[team]['teamName']);*/
imgCountry.setAttribute('src', dataObject[country]['countryImg']);
imgCountry.setAttribute("width", "400");
imgCountry.setAttribute("height", "300");
console.log(country);
ulListElem[0].innerHTML = dataObject[country]['countryId'];
ulListElem[1].innerHTML = dataObject[country]['countryName'];
ulListElem[2].appendChild(imgCountry);
ulListElem[3].innerHTML = dataObject[country]['countryInfo']['headOfState'];
ulListElem[4].innerHTML = dataObject[country]['countryInfo']['capital'];
ulListElem[5].innerHTML = dataObject[country]['countryInfo']['population'];
ulListElem[6].innerHTML = dataObject[country]['countryInfo']['area'];
ulListElem[7].innerHTML = dataObject[country]['countryInfo']['language'];
}
}
}
var countriesDate = new Countries();
countriesDate.getCountries();
});

You are setting the same UI elements (img and ul) twice inside a loop. When the loop runs first time, the values are set from the first array element. When the loop runs second time, the SAME elements are overwritten with the new values.
To properly display all elemts from the JSON array, you need two sets of UI elements in the index.html page e.g. two imgs, two uls etc.

Related

Firebase: sort alphabetically a nested field in last children

I have this Firebase database with the following data:
Here is a part of the JSON file:
"SWPL6X" : {
"-LznFoTKvdc5318O97h_" : {
"direction" : "in",
"excluded" : false,
"in" : 422,
"multiplier_out" : 1.05,
"name" : "MaM.OUT.90F8",
"out" : 6582,
"total" : -6160
},
"-M2ZQU2azNc-JTKKXojU" : {
"direction" : "in",
"excluded" : false,
"in" : 316,
"multiplier_out" : 1.05,
"name" : "CdG.Out.96A4",
"out" : 2509,
"total" : -2193
},
"-M3zVSWzqb4TaezY1Kua" : {
"direction" : "in",
"excluded" : false,
"in" : 4806,
"name" : "MaM.in.3FBC",
"out" : 748,
"total" : 4058
},
I just need to order alphabetically the last children by the field "name" (String) but I can't find a way to achieve it.
The code before I tried to sort is the following:
getSensors: function(uid, event_id, success){
var ref=firebase.database().ref('clients_events_sensors/'+ uid+ '/'+ event_id);
kap.firebase.bindings.liveObject(ref, success, function(e){
kap.log('cant get client event sensors', e)
});
},
I tried changing the first line to this with no effect:
var ref=firebase.database().ref('clients_events_sensors/'+ uid+ '/'+ event_id).orderByChild('name');
This function is only called once here, the logs retrieved keep the same order as the one coming initially from Firebase:
app.data.getSensors(kap.page.uid, kap.page.event_id, function(sensors) {
$.each(sensors, function(k, sensor){
//remove picture to avoid blowing localstorage memory
sensor.photo=null;
//Replace total by in+out/2 in the app only
sensor.total = Math.round((sensor.in+sensor.out) / 2);
sensor.sum = sensor.in+sensor.out;
});
kap.log('got sensors', sensors);
kap.page.sensors = sensors;
kap.page.fill();
});
The log:
got sensors {
"-LznFoTKvdc5318O97h_":{"direction":"in","excluded":false,"in":492,"multiplier_out":1.05,"name":"MaM.OUT.90F8","out":6983,"total":3738,"photo":null,"sum":7475},
"-M2ZQU2azNc-JTKKXojU":{"direction":"in","excluded":false,"in":339,"multiplier_out":1.05,"name":"CdG.Out.96A4","out":2686,"total":1513,"photo":null,"sum":3025},
"-M3zVSWzqb4TaezY1Kua":{"direction":"in","excluded":false,"in":5150,"name":"MaM.in.3FBC","out":836,"total":2993,"photo":null,"sum":5986},
"-M9Y7Ed7JtPSKTUQXRhd":{"direction":"in","excluded":false,"in":470,"multiplier_out":1.05,"name":"Volt.Out.99CE","out":2323,"total":1397,"photo":null,"sum":2793},
"-MAa2FZ5z5fMejpSL7zp":{"direction":"in","excluded":false,"in":4615,"multiplier_in":1,"name":"CdG.In_A011","out":486,"total":2551,"photo":null,"sum":5101},
"-MAa2QX5rvjWlT_2z7YQ":{"direction":"in","excluded":false,"in":3729,"name":"Volt.In_A013","out":1203,"total":2466,"photo":null,"sum":4932},
"-MAa2UaqVDyxQrQojFiR":{"direction":"in","excluded":false,"in":400,"multiplier_out":1.05,"name":"Pagnol.Out_A014","out":2205,"total":1303,"photo":null,"sum":2605},
"-MBiKvKAAWQkU8RABWR0":{"direction":"in","excluded":false,"in":2613,"name":"Pagnol.In_A015","out":987,"total":1800,"photo":null,"sum":3600}}
Am I missing something?

Accessing arrays

I'm using the Raphaƫl framework to draw dynamic shapes (which make them clickeable, you can make them glow...).
I can't access the array correctly.
I've created an array :
var siegeurs = {
1 : [{
"Nom" : "User1",
"Photo" : "url"
}],
2 : [{
"Nom" : "User2",
"Photo" : "url"
}],
3 : [{
"Nom" : "User3",
"Photo" : "url"
}],
4 : [{
"Nom" : "User4",
"Photo" : "url"
}],
5 : [{
"Nom" : "User5",
"Photo" : "url"
}]
};
These are the shapes that the framework draw :
sieges["1"] = assembly.path("M236.51 ... 108");
sieges["2"] = assembly.path("M483.51 ... 71");
sieges["3"] = assembly.path("M427.51 ... 272");
sieges["4"] = assembly.path("M135.51 ... 348");
sieges["5"] = assembly.path("M617.51 ... 413");
They are like object so you can interact with them.
This is the loop :
for(var siegeNum in sieges) {
(function (siege) {
siege.attr(style); //apply style to shapes
siege[0].addEventListener("mouseover", function() {
siege.animate(hoverStyle, animationSpeed); //add hoverstyle when hovered
//The line I can't figure out
document.getElementById("textelement").innerHTML = siegeurs[siegeNum]["Nom"];
//The line I can't figure out
}, true);
siege[0].addEventListener("mouseout", function() {
siege.animate(style, animationSpeed);
document.getElementById("textelement").innerHTML = baseTxt;
}, true);
})
(sieges[siegeNum]);
}
textelement is a basic text I try to modify when a shape is hovered.
Actually, when I hover a shape, the text goes to "undefined".
I tried to do this way just to check :
document.getElementById("textelement").innerHTML = siegeurs[siegeNum];
But when I hover, the text goes to [object Object].
Any help is appreciated.
Each value in your siegeurs object is an array, so the needed inner property "Nom" should be accessed as:
...
document.getElementById("textelement").innerHTML = siegeurs[siegeNum][0]["Nom"];

Store ajax response object in global variable --- Fields get missing

I'm implementing an asynchronous webpage in Grails where I make a call to a controller and render the response as a D3.js network. I stored the object into a global variable for further use. The function worked fine when data is returned. However when I tried to use the object later I found some fields became undefined.
var similar;
function asynchroNetwork() {
var jsonData = $.ajax({
url: "${createLink(controller:'environment', action:'asynchro')}",
dataType: "json",
async: true
}).done(function(jsonData) {
console.log(jsonData);
//console.log(jsonText);
document.getElementById("result").innerHTML="Done";
console.log(jsonData.all);
//set global variable
similar=jsonData;
console.log("The object got");
console.log(similar);
draw();
});;
}
function draw(){
console.log(similar);
//draw the network based on object
}
The controller returns the following JSON:
{
"\u521B\u4E1A" : {
"nodes" : [{
"group" : 1,
"name" : "\u6c88\u9633\u8f9b\u98962\u4e16"
}
],
"links" : []
},
"all" : {
"nodes" : [{
"group" : 1,
"name" : "qwe25322570"
}, {
"group" : 1,
"name" : "\u660e\u5fb7\u7b03\u884c"
}, {
"group" : 1,
"name" : "\u6c88\u9633\u53ef\u4e50"
}, {
"group" : 1,
"name" : "\u6c88\u9633\u5f6d\u79c0\u8363"
}, {
"group" : 1,
"name" : "\u6c88\u9633\u738b\u632f\u534e"
}, {
"group" : 1,
"name" : "\u6c88\u9633\u8f9b\u98962\u4e16"
}
],
"links" : [{
"value" : 1.0,
"target" : "\u6c88\u9633\u8f9b\u98962\u4e16",
"source" : "\u660e\u5fb7\u7b03\u884c"
}, {
"value" : 1.0,
"target" : "\u6c88\u9633\u8f9b\u98962\u4e16",
"source" : "qwe25322570"
}
]
}
}
In the draw() function it uses similar[all] to draw a graph. But in the links field I see the fields source and target are all undefined, while all fields in the nodes are all fine.
I don't think the encoding is the cause because nodes also contains UTF8 characters in the fields but none got missing. After the object is passed back from asychronous function the object similar is okay, but the next time draw() is called, I can see the field links go undefined.
Does anyone know what could be the cause of this problem? I guess it maybe related to nested fields.
Did you try passing your data as an argument to the draw function? If not, then:
In your ajax callback:
similar = jsonData;
draw(similar) //pass the json
draw function:
function draw(json) {
console.log(json);
}

simple ajax request to load external json file

I'm learning ajax.... I am trying to make a basic request from a json file, which is in the same folder as my index.html, but for some reason it says undefined :( I can see the error is on the variable people, but I can't catch why it's undefined....
html:
<div id="personName"></div>
javascript:
var xhr = new XMLHttpRequest(); //it holds the ajax request
xhr.onreadystatechange = function() { //callback
if(xhr.readyState === 4) {
var people = JSON.parse(xhr.responseText);//it takes the string from the response and it converts it in a javascript object
console.log(people);
for (var i=0; i<people.length; i += 1) {
var htmlCode = "<p>" + people[i].name + "</p>";
}
document.getElementById('personName').innerHTML = htmlCode;
} else {
console.log(xhr.readyState);
}
};
xhr.open('GET', 'addresses.json');
xhr.send();
addresses.json:
{
"people": [
{
"position" : "1",
"name" : "Familia Molina Fernandez",
"streetType" : "C/",
"streetName " : "Nuria",
"streetNumber" : "40",
"floor" : "",
"flat" : "",
"zipCode" : "08202",
"city" : "Sabadell",
"state" : "Barcelona",
"country" : "Spain"
},
{
"position" : "2",
"name" : "Familia Astals Fernandez",
"streetType" : "Avda/",
"streetName " : "Polinya",
"streetNumber" : "61",
"floor" : "1",
"flat" : "1",
"zipCode" : "08202",
"city" : "Sabadell",
"state" : "Barcelona",
"country" : "Spain"
}
]
}
Any ideas?
Cheers!!!!
Try console.log(people); and take a look at the object to which your variable refers. (Hint: it's not what you think it is!)
Your variable people refers to an object with only one attribute named "people". That attribute is an array. So with that JSON structure, your code could be written:
var data = JSON.parse(...)
var people = data.people;
(alternatively, I might redesign the JSON and remove the extra level of indirection: just encode the array itself without wrapping it in an object that contains nothing else)

DataTables with different number of columns

I am loading data using ajax and generating column names dynamically in my DataTable. My DataTable has different number of columns, depending on the selection by user.(There is a drop-down list).
For example, there are 2 options in drop-down list as Southern Province and Northern Province. Southern Province table has 4 columns and Northern Province table has 6 columns.
Scenario 1
First user select Southern Province which has 4 columns. Then it generates table without no errors, But after that if user select Northern Province which has 6 columns, table not generate and js console print error as below.
Uncaught TypeError: Cannot read property 'style' of undefined jquery.dataTables.js:3828
Scenario 2
First user select Northern Province which has 6 columns. Then it generates table without no errors, But after that if user select Southern Province which has 4 columns, table not generate and js console print error as below.
Uncaught TypeError: Cannot read property 'mData' of undefined jquery.dataTables.js:6122
But if both table has same number of columns, both tables generate without errors.
How can I solve this ?
Here is the JS Code
jQuery(document)
.ready(
function() {
$('#province-list').change(
function() {
var prov = $(this).val();
if (prov == "sp") {
make_SP();
} else if (prov == "np") {
make_NP();
}
});
function make_SP() {
$("#dataTables-res_item")
.dataTable(
{
"bDestroy" : true,
"bProcessing" : false,
"bServerSide" : true,
"sAjaxSource" : "/province_list_view?p_name=sp",
"aoColumns" : [
{
"mData" : "result_date",
"sTitle" : "Result Date"
},
{
"mData" : "result_day",
"sTitle" : "Result Day"
},
{
"mData" : "draw_number",
"sTitle" : "Draw Number"
},
{
"mData" : "draw_time",
"sTitle" : "Draw Time"
} ],
"order" : [ [ 0, "desc" ] ]
});
};
function make_NP() {
$("#dataTables-res_item")
.dataTable(
{
"bDestroy" : true,
"bProcessing" : false,
"bServerSide" : true,
"sAjaxSource" : "/province_list_view?p_name=np",
"aoColumns" : [
{
"mData" : "result_date",
"sTitle" : "Result Date"
},
{
"mData" : "result_day",
"sTitle" : "Result Day"
},
{
"mData" : "draw_number",
"sTitle" : "Draw Number"
},
{
"mData" : "draw_time",
"sTitle" : "Draw Time"
},
{
"mData" : "draw_place",
"sTitle" : "Draw Place"
},
{
"mData" : "draw_person",
"sTitle" : "Agent"
} ],
"order" : [ [ 0, "desc" ] ]
});
};
});
I faced the same issue when my updated data had different number of columns than the previous data. The recipe is really simple! In the scenario when there is a change in number of columns, Destroy function works in conjunction with $("#datatable").empty();. So before reloading data your code would contain following lines:
if (dataTableObject) { // Check if DataTable has been previously created and therefore needs to be flushed
dataTableObject.fnDestroy(); // destroy the dataTableObject
// For new version use table.destroy();
$('#' + DataTableDivID).empty(); // Empty the DOM element which contained DataTable
// The line above is needed if number of columns change in the Data
}
// DataTable data loading/reloading codes comes here
So overall, your code may look like this:
if(dataTableObject) { // Check if table object exists and needs to be flushed
dataTableObject.fnDestroy(); // For new version use table.destroy();
$('#myTable').empty(); // empty in case the columns change
}
var data = (province=='sp') ? sp : np;
var columns = (province=='sp') ? spColumns : npColumns;
dataTableObject = $('#myTable').DataTable({
columns: columns,
data: data
});
I think the safest way is to remove the table completely, and then re-insert it to the DOM before reinitialising. Seems to me that dataTables not completely removes all generated content, thats why the error(s) occurs (for different reasons). In theory it should work as above, more or less, but it doesn't. Consider this solution :
[full source in the demo link below]
var dataTable,
domTable,
htmlTable = '<table id="example"><tbody></tbody></table>';
function initDataTable(province) {
if ($.fn.DataTable.fnIsDataTable(domTable)) {
dataTable.fnDestroy(true);
$('body').append(htmlTable);
}
var data = (province=='sp') ? sp : np;
var columns = (province=='sp') ? spColumns : npColumns;
dataTable = $("#example").dataTable({
aaData : data,
aoColumns : columns
/* other options here */
});
domTable = document.getElementById('example');
}
$('#province-list').change(function() {
var prov = $(this).val();
initDataTable(prov);
});
This works. See demo -> http://jsfiddle.net/gss4a17t/
Basically it is the same as in OP, but instead of having different functions for different provinces, I have made different aoColumns for different provinces and so on. And instead of relying on bDestroy, I remove the entire <table> with dataTable.fnDestroy(true) (both DOM and and dataTables injections) and then reinserts the <table>-skeleton before reinitialising the dataTable.
I dont know if that is adaptable to OP's need, but this is how I would do it. It is more flexible for future changes, and the aoColumns-objects can be autogenerated from a script or achieved from the server by AJAX (if you want to have different titles for different languages, for example). "Belt and braces" :)
There is good solution up there but after ran into this question, dynamism still ring the bell on my mind. i would like to share this , not a export in js. So please comment.
function genericAjaxCall(url, tableId, _header, _dataMapping, isData,
isEditDelete) {
if (!isData) {
$.ajax({
url : url,
method : "GET",
dataType : "JSON",
success : function(data) {
var editDeletUrl = url.split("/");
var dataArray = createArray(_header, data, _dataMapping, url,
isEditDelete)
createListHeading(tableId, dataArray, false);
initDT(tableId, dataArray);
},
error : function(xhr) {
console.log(xhr);
openErrorModal("Guru", xhr.responseText);
}
});
} else {
var dataArray = createArray(_header, url, _dataMapping);
console.log(dataArray);
var finalData = dataArray + objName;
console.log(finalData);
createListHeading(tableId, dataArray, false);
initDT(tableId, dataArray);
}
}
function createArrayWithDelete(_header, data, _dataMapping, url) {
var posts = {};
posts.postDT = []
for (var i = 0; i < data.length; i++) {
var jsonData = {};
for (var j = 0; j < _header.length; j++) {
if (_dataMapping[j].indexOf('.') !== -1) {
var parts = _dataMapping[j].split(".");
if (String(data[i][parts[0]][parts[1]]).indexOf('*') !== -1) {
jsonData[_header[j]] = data[i][parts[0]][parts[1]].bold()
.replace("*", "");
} else {
jsonData[_header[j]] = data[i][parts[0]][parts[1]];
}
} else {
if (String(data[i][_dataMapping[j]]).indexOf('*') !== -1) {
jsonData[_header[j]] = data[i][_dataMapping[j]].bold()
.replace("*", "");
} else {
jsonData[_header[j]] = data[i][_dataMapping[j]];
}
}
}
if (_header[_header.length - 1]) {
jsonData["Action"] = deleteOnly(url,
data[i][_dataMapping[_dataMapping.length - 1]]);
}
posts.postDT.push(jsonData);
}
return posts.postDT;
}
function createListHeading(tableId, data, isAction) {
var posts = {
post : []
};
$.each(data[0], function(key, value) {
posts.post.push({
"mDataProp" : key,
"sTitle" : key
/* "sType" : "string" */
});
});
cols = posts.post
}
function initDT(tableId, results) {
// Construct the measurement table
data_table = $('#' + tableId).DataTable({
"iDisplayLength" : 10,
scrollCollapse : true,
"aaSorting" : [],
"aaData" : results,
"aoColumns" : cols
});
$('#' + tableId).DataTable().columns.adjust();
}
And this is how i call ,
$(function() {
var header = [ "H1", "H2", "H3", "H4" ];
var dataMapping = [ "d1", "d2", "d3", "d3" ];
genericAjaxCall("ajaxurlWhichreturnJSON", "tableId", header, dataMapping,
false, true);
});
Here d1, d2... are the key of your ajax response. Now we do not need to worry that which value user select. Note : this is not direct solution of this question but it is figurative
I know this is an old question, but since I spent several hours trying to solve it with DataTables 1.10.18, I publish it with the hope that it will help someone. I used JavaScript arrays as data source, and jQuery 1.12.4. It is based on #davidkonrad's answer.
HTML:
select province
<select id="province-list">
<option value="sp">sp</option>
<option value="np">np</option>
</select>
<br><br>
<div id="table-container">
<table id="example" class="display"></table>
</div>
JS:
var sp = [
[ 'col1', 'col2'] ,
[ 'col11', 'col22']
];
var np = [
[ 'col1', 'col2', 'col3', 'col4' ],
[ 'col11', 'col22', 'col33', 'col44' ]
];
var spColumns = [
{ title : "column1" },
{ title : "column2" }
];
var npColumns = [
{ title : "column1" },
{ title : "column2" },
{ title : "column3" },
{ title : "column4" }
];
var dataTable,
htmlTable = '<table id="example" class="display"></table>';
function initDataTable(province) {
if ($.fn.DataTable.isDataTable('#example')) {
dataTable = $('#example').DataTable();
dataTable.destroy(true);
$('#table-container').empty();
$('#table-container').append(htmlTable);
}
var data = (province=='sp') ? sp : np;
var columns = (province=='sp') ? spColumns : npColumns;
dataTable = $('#example').DataTable( {
"data": data,
"columns": columns
} );
}
$(document).ready(function() {
initDataTable('sp');
$('#province-list').change(function() {
var prov = $(this).val();
initDataTable(prov);
});
});

Categories

Resources