A company email-generating application I'm working on has an autocomplete input to autofill email theme data into a form. The data is returned as a JSON object, but a couple of the object values extraps and extraul contain multidimensional arrays. I'm able to get the plain key:value data just fine out in the response, but I can't seem to figure out how to pull the arrays in so I can loop over them to update certain sections of the form.
Here's a look at some of the JSON code coming in:
0:
emaildate: "2019-01-10"
extraps: Array(2)
0: {extrap: "test paragraph", position: 1}
1: {extrap: "another paragraph", position: 3}
length: 2
__proto__: Array(0)
extraul: Array(4)
0: {ulid: 1, position: 2, li: "list item 1", liposition: 1}
1: {ulid: 1, position: 2, li: "list item 2", liposition: 2}
2: {ulid: 1, position: 2, li: "list item something new", liposition: 3}
3: {ulid: 1, position: 2, li: "A new list item", liposition: 4}
length: 4
__proto__: Array(0)
id: 44
label: "Some Kind of Email Theme - 2019-01-10"
lastupdated: "2019-01-06 02:00:04"
store: "Premier"
themedesc: "Here's a description of the theme."
themeimage: null
themeincludeextrap: 1
themeincludeul: 1
themelink: "some-kind-of-email-theme"
themelinkinclude: 1
themename: "Some Kind of Email Theme"
themenotes: "Some notes about it"
themesortorder: 0
value: "Some Kind of Email Theme"
__proto__: Object
length: 1
__proto__: Array(0)
And here's a look at the javascript to bring it in from autotheme.php:
//Autofill Theme Info based on text entry
$( "#themename" ).autocomplete({
source: function( request, response ) {
$.ajax({
url: "autotheme.php",
type: "GET",
dataType: "json",
data: {
q: request.term
},
success: function(data) {
console.log(data);
response($.map(data, function(item) {
return {
id: item.id,
value: item.value,
label: item.label,
themename: item.themename,
themenotes: item.themenotes,
themedesc: item.themedesc,
themeimage: item.themeimage,
themeincludeextrap: item.themeincludeextrap,
themeincludeul: item.themeincludeul,
themelinkinclude: item.themelinkinclude,
themelink: item.themelink,
themeextraps: item.extraps,
themeextraul: item.extraul
}
}))
},
error: function(errorThrown){
console.log(errorThrown);
console.log("There is an error with theme autocomplete.");
}
});
},
minLength: 2,
select: function(event, ui) {
if (ui.item) {
$this = $(this);
$('#themeid').val('');
$('#extratext').html('');
$('#themename').val(ui.item.themename);
$('#themenotes').val(ui.item.themenotes);
$('#themedesc').val(ui.item.themedesc);
var themeimage = ui.item.themeimage;
var themeincludeextrap = ui.item.themeincludeextrap;
var themeincludeul = ui.item.themeincludeul;
var themelinkinclude = ui.item.themelinkinclude;
var themeextraps = ui.item.extraps;
var themeextraul = ui.item.extraul;
if(themeextraps !== undefined) {
var extrapcount = themeextraps.length;
}
if(themeextraul !== undefined) {
var extraulcount = themeextraul.length;
}
if((themeextraps !== undefined) || (themeextraul !== undefined)) {
var extratextpositions = {};
$.each(themeextraps, function(i, themeextraps) {
extratextpositions[themeextraps.position] = 'p';
})
$.each(themeextraul, function(i, themeextraul) {
extratextpositions[themeextraul.position] = 'ul';
})
$.each(extratextpositions, function(key, value) {
if(extratextpositions[key] == 'p') {
addExtraP.call(this);
} else {
addExtraUl.call(this);
}
});
$('#themelink').val(ui.item.themelink);
if(themelinkinclude == 1) {
$('#themelinkinclude').prop("checked", true);
} else {
$('#themelinkinclude').prop("checked", false);
}
event.preventDefault();
}
},
open: function(event, ui) {
$(".ui-autocomplete").css("z-index", 1000);
},
complete: function(){
$("#themename").removeClass("ui-autocomplete-loading");
}
}
});
I'm able to get the simple key:value values just fine, but I get undefined for the arrays. I'm sure there's a different way I need to pull those in, but I don't know how and can't seem to find the answer in other threads on here. Any help would be greatly appreciated!
Figured out a way to get around this problem, thanks to some help from #Bibberty. I'm not sure if this is the most graceful or easy way to solve it, but it worked for me. I created an array from the JSON data values, then created variables from the arrays within the data array and added them to the response return value. Here's the new functional code (or, at least, the part that matters):
//Autofill Theme Info based on text entry
$( "#themename" ).autocomplete({
source: function( request, response ) {
$.ajax({
url: "autotheme.php",
type: "GET",
dataType: "json",
data: {
q: request.term
},
success: function(data) {
const results = data.map(function (value, label) {
return [value];
})
var extraps = results[0][0]['extraps'];
var extraul = results[0][0]['extraul'];
response($.map(data, function(item) {
return {
id: item.id,
value: item.value,
label: item.label,
themename: item.themename,
themenotes: item.themenotes,
themedesc: item.themedesc,
themeimage: item.themeimage,
themeincludeextrap: item.themeincludeextrap,
themeincludeul: item.themeincludeul,
themelinkinclude: item.themelinkinclude,
themelink: item.themelink,
extraps: extraps,
extraul: extraul
}
}))
$("#themename").removeClass("ui-autocomplete-loading");
},
error: function(errorThrown){
console.log(errorThrown);
console.log("There is an error with theme autocomplete.");
}
});
},
minLength: 2,
select: function(event, ui) {
if (ui.item) {
$this = $(this);
console.log(ui.item.extraps);
$('#themeid').val('');
$('#extratext').html('');
$('#themename').val(ui.item.themename);
$('#themenotes').val(ui.item.themenotes);
$('#themedesc').val(ui.item.themedesc);
var themeimage = ui.item.themeimage;
var themeincludeextrap = ui.item.themeincludeextrap;
var themeincludeul = ui.item.themeincludeul;
var themelinkinclude = ui.item.themelinkinclude;
var themeextraps = ui.item.extraps;
var themeextraul = ui.item.extraul;
if(themeextraps !== undefined) {
var extrapcount = themeextraps.length;
}
if(themeextraul !== undefined) {
var extraulcount = themeextraul.length;
}
...
debugging screenshot
$.ajax({
url: postUrl,
type: 'GET',
dataType: 'json',
data: { "id": num },
contentType: "application/json; charset=utf-8",
success: function (data) {
$.each(data, function (id, allFollowers) {
result += 'Title : ' + **data** + '<br/>';
});
I've tried: data.allFollowers[0].screeName, data[0].allFollowers[0].screeName...
I can see these values exist here in debug mode, however it returns a null error..?
Based on your screenshot, I'm assuming the data somewhat looks like this:
//data is an object, with an array of allFollowers objects
var data = {
"allFollowers": [{
"AlternateText": "no photo",
"profileImage": "http://foo.com/foo",
"screenName": "foo",
"userID": 15785100
},
{
"AlternateText": "no photo",
"profileImage": "http://bar.com/bar",
"screenName": "bar",
"userID": 12345678
}
]
};
You're iterating on data only/instead of its child array (allFollowers). So you'll have to go one level deeper:
$.each(data, function(key, obj) {
$.each(obj, function(i, value){
console.log("screen name %i: %o, User ID: %o", i, value.screenName, value.userID);
})
})
Console:
screen name 0: "foo", User ID: 15785100
screen name 1: "bar", User ID: 12345678
Hth...
I think your mistake is about using $.each function. You should refer to your data using some code like:
$.each(data, function (id, follower) {
result += 'Title : ' + follower + '<br/>';
});
For more info refer to this jQuery API Documentation.
I'm using one api in which the response is coming in two columns but in one column there are many parameters, I need to decode one column and want to show in different columns.
Column name coming from api timestamp, dataFrame, I need to show in 3 columns timestamp, oil temperature and winding temperature. I need to add one more column in datatable to show the values in the datatable.
sample json data
[{
"timestamp": "2018-07-21T07:56:23.838Z",
"dataFrame": "HA=="
},
{
"timestamp": "2018-07-21T08:16:23.902Z",
"dataFrame": "HA=="
}
]
output
Expected Output
Timestamp, Oil Temp, winding temp in 3 separate columns
code
<script>
window.onload = getddata();
function getddata() {
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function () {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
var Readings = JSON.parse(xmlhttp.responseText);
//jquery data table - start
$(document).ready(function () {
$('#example').DataTable({
columnDefs: [{
"targets": 1,
"render": function (data, type, row, meta) {
var hexvalue =base64toHEX(data);
var deviceid= hexToDec(hexvalue.substr(1,1));
var oil_temp= hexToDec(hexvalue.substr(2,2));
var winding_temp= hexToDec(hexvalue.substr(4,2));
return 'oil temp: ' + oil_temp + ', Winding Temp: ' + winding_temp + ' ;
}
},
{
"targets": 0,
"render": function (data, type, row, meta) {
var updDate= UtcToIst(data).toLocaleDateString();
var updTime= UtcToIst(data).toLocaleTimeString();
var updDateTime=updDate + ", " + updTime;
return updDateTime ;
}
}
}
],
data: Readings,
columns: [{
"data": "timestamp"
}, {
"data": "dataFrame"
}
]
});
});
//data table code -close
}
};
xmlhttp.open("GET", "https://.., true);
xmlhttp.setRequestHeader("Authorization", "Basic a2VybmV");
xmlhttp.setRequestHeader("Content-type", "Application/json");
xmlhttp.send();
}
</script>
It seems to me the code is a little bit overcomplicated. Why not just reuse dataFrame over multiple columns? Perhaps I misunderstand the question ...
var table = $('#example').DataTable({
data: sampleReadings,
columns: [
{ data: 'timestamp', title: 'timestamp',
render: function(data) {
return data
/* dont know what UtcToIst is
var updDate= UtcToIst(data).toLocaleDateString();
var updTime= UtcToIst(data).toLocaleTimeString();
var updDateTime=updDate + ", " + updTime;
return updDateTime ;
*/
}
},
{ data: 'dataFrame', title: 'deviceid',
render: function(data) {
var hexvalue = base64toHEX(data);
return hexToDec(hexvalue.substr(1,1));
}
},
{ data: 'dataFrame', title: 'Oil temp',
render: function(data) {
var hexvalue = base64toHEX(data);
return hexToDec(hexvalue.substr(2,2));
}
},
{ data: 'dataFrame', title: 'Winding temp',
render: function(data) {
var hexvalue = base64toHEX(data);
return hexToDec(hexvalue.substr(4,2));
}
},
//I guess there is more data hidden in dataFrame
//You can almost copy paste new columns here
]
})
If you have 10.000 records it would be a good idea to cache the output from base64toHEX.
demo -> http://jsfiddle.net/fn0yL361/
You can simply add a new column and render related value. Please update the data tables column.
https://datatables.net/reference/option/columns.name
{ columnDefs: [{
"targets": 2,
"name": "winding temp",
"render": function (data, type, row, meta) {
var hexvalue =base64toHEX(data);
var deviceid= hexToDec(hexvalue.substr(1,1));
var oil_temp= hexToDec(hexvalue.substr(2,2));
var winding_temp= hexToDec(hexvalue.substr(4,2));
return 'Winding Temp: ' + winding_temp ;
}
},{
"targets": 1,
"name": "Oil temp",
"render": function (data, type, row, meta) {
var hexvalue =base64toHEX(data);
var deviceid= hexToDec(hexvalue.substr(1,1));
var oil_temp= hexToDec(hexvalue.substr(2,2));
var winding_temp= hexToDec(hexvalue.substr(4,2));
return 'oil temp: ' + oil_temp ;
}
},
{
"targets": 0,
"name" : "Timestamp",
"render": function (data, type, row, meta) {
var updDate= UtcToIst(data).toLocaleDateString();
var updTime= UtcToIst(data).toLocaleTimeString();
var updDateTime=updDate + ", " + updTime;
return updDateTime ;
}
}
],
data: Readings,
columns: [{
"data": "timestamp"
}, {
"data": "dataFrame"
},
{
"data": "dataFrame"
}
]
Here is an example, because there are spaces in Name so need some extra code to get field:
var str = "{timestamp: 'xxx', dataFrame: 'Old Time: xx, winding Time: yyyy, Ambient Time: zzzz'}";
var objOrg = JSON.parse(str);
var newJSon = [{}];
foreach (var itm in objOrg)
{
var new3Fields = itm.dataFrame;
var arr = new3Fields.split(',')
var newItem = {};
newItem.timestamp = itm.timestamp;
newItem.OldTime = JSON.parse(arr[0]).['Old Time'];
newItem.WindingTime = JSON.parse(arr[1]).['winding Time'];
newItem.AmbientTime = JSON.parse(arr[2]).['Ambient Time'];
newJSon += newItem;
}
newJSon <--- This is a list with 4 columns
I have a rails app that fetches currency information data of the value of the sterling pound compared to the Kenyan shilling from a JSON API.
I want to use this data to plot a time-series graph of the value of the pound over a long period of time.
I'm using AJAX to populate data to a highcharts chart and my code is as follows:
<div id="currency", style="width: 220px, height:320px">
<script type="text/javascript">
$(document).ready(function(){
localhost = {}; //global namespace variable
localhost.currenctHTML = ""; //currency HTML built here
localhost.currencyValue = []; //array of percentage changes
localhost.currencyDate = []; //array of currency names
localhost.chart1 = {yAxisMin : null, yAxisMax : null};//obj holds things belonging to chart1
var url = '/forexes.json'
$.ajax({
url: url,
cache: false,
dataType: 'jsonp', //will set cache to false by default
context: localhost,
complete: function(data){
var a=JSON.parse(data.responseText);
// console.log(a);
var data_mapped = a.map(function (data){
return data.forex;
}).map(function (data) {
return {
currencyDate: data.published_at,
currencyValue: data.mean
}
});
this.currencyDate = _.pluck(data_mapped, 'currencyDate');
this.currencyValue = _.pluck(data_mapped, 'currencyValue');
console.log(this.currencyDate);
this.chart1.data.series[0].data = this.currencyValue;
this.chart1.data.xAxis.categories = this.currencyDate;
chart = new Highcharts.Chart(this.chart1.data);
}
});
localhost.chart1.data = { //js single-threaded, this obj created before callback function completed
chart: {
renderTo: "currency"
},
title: {
text: "Forex by Day"
},
xAxis: {
categories: null, //will be assigned array value during ajax callback
title: {
text: null
}
},
yAxis: {
title: {
text: "Pounds"
}
},
tooltip: {
formatter: function() {
return Highcharts.dateFormat("%B %e, %Y", this.x) + ': ' +
"$" + Highcharts.numberFormat(this.y, 2);
}
},
series: [{
name: 'Pound',
data: null
}
]
};
});
</script>
</div>
**** returns
this.chart1.data.xAxis.categories = ["2003-01-01T00:00:00.000Z", "2003-01-02T00:00:00.000Z", "2003-01-03T00:00:00.000Z", "2003-01-04T00:00:00.000Z", "2003-01-05T00:00:00.000Z"]
this.chart1.data.series[0].data = [147.653, 148.007, 147.971, 148.202, 148.384, 147.888]
How do I use this data to generate a highstocks line chart resembling this
In the highstock you cannot use categories, only datetime type, so you should parse your data to timestamp and use it in the data.
I am attempting to create a dynamic flot graph dependant upon the data given to it, my flot graph is using JSON for its information and here is an example of the dataset:
{
"total":[[1377691200,115130],[1377694800,137759],[1377698400,137759],[1377702000,137759],[1377705600,137759],[1377709200,139604],[1377712800,137759],[1377716400,137759],[1377720000,137759],[1377723600,137759],[1377727200,137759],[1377730800,138156],[1377734400,137759],[1377738000,137759],[1377741600,137759],[1377745200,137759],[1377748800,138156],[1377752400,137759],[1377756000,137759],[1377759600,168831],[1377763200,137759],[1377766800,0],[1377770400,0]],
"dev0":[[1377691200,115130],[1377694800,137759],[1377698400,137759],[1377702000,137759],[1377705600,137759],[1377709200,139604],[1377712800,137759],[1377716400,137759],[1377720000,137759],[1377723600,137759],[1377727200,137759],[1377730800,138156],[1377734400,137759],[1377738000,137759],[1377741600,137759],[1377745200,137759],[1377748800,138156],[1377752400,137759],[1377756000,137759],[1377759600,168831],[1377763200,137759],[1377766800,0],[1377770400,0]],
"dev1":[[1377691200,0],[1377694800,0],[1377698400,0],[1377702000,0],[1377705600,0],[1377709200,0],[1377712800,0],[1377716400,0],[1377720000,0],[1377723600,0],[1377727200,0],[1377730800,0],[1377734400,0],[1377738000,0],[1377741600,0],[1377745200,0],[1377748800,0], [1377752400,0],[1377756000,0],[1377759600,0],[1377763200,0],[1377766800,0],[1377770400,0]]
}
The script i have created already:
$(".bytes_portal_pop").click(function(e) {
e.preventDefault();
var graph=$(this).data('graph');
var range=$(this).data('range');
var divid=$(this).data('divid');
var title=$(this).data('boxtitle');
$.getJSON("/action/sites/GetFlotStats/?graph=" + graph + "&range=" + range, function(json) {
//succes - data loaded, now use plot:
var plotarea = $("#" + divid);
var dev0=json.dev0;
var dev1=json.dev1;
$.plot(
$("#" + divid),
[
{
data: dev0,
lines:{show: true, fill: true},
label: "dev0",
},
{
data: dev1,
lines:{show: true, fill: true},
label: "dev1",
},
],
{
xaxis: {mode:"time"},
grid: {hoverable: true},
tooltip: true,
tooltipOpts: {
content: "Traffic: %y GB"
}
}
);
});
$("#boxtitleB_flot").html(title);
});
This way works fine and displays the two lines as i need however i would like it to be dynamic i.e. so i dont have to define each graph line i believe todo this i simply need a for or each() loop on the
var dev0=json.dev0;
and
{
data: dev0,
lines:{show: true, fill: true},
label: "dev0",
},
Any help achieving this would be much appreciated.
Correct, just loop it and generate your series objects dynamically.
Given a json return like:
jsonObj = {
"total":[[1377691200,115130],[1377694800,137759],[1377698400,137759],[1377702000,137759],[1377705600,137759],[1377709200,139604],[1377712800,137759],[1377716400,137759],[1377720000,137759],[1377723600,137759],[1377727200,137759],[1377730800,138156],[1377734400,137759],[1377738000,137759],[1377741600,137759],[1377745200,137759],[1377748800,138156],[1377752400,137759],[1377756000,137759],[1377759600,168831],[1377763200,137759],[1377766800,0],[1377770400,0]],
"dev0":[[1377691200,115130],[1377694800,137759],[1377698400,137759],[1377702000,137759],[1377705600,137759],[1377709200,139604],[1377712800,137759],[1377716400,137759],[1377720000,137759],[1377723600,137759],[1377727200,137759],[1377730800,138156],[1377734400,137759],[1377738000,137759],[1377741600,137759],[1377745200,137759],[1377748800,138156],[1377752400,137759],[1377756000,137759],[1377759600,168831],[1377763200,137759],[1377766800,0],[1377770400,0]],
"dev1":[[1377691200,0],[1377694800,0],[1377698400,0],[1377702000,0],[1377705600,0],[1377709200,0],[1377712800,0],[1377716400,0],[1377720000,0],[1377723600,0],[1377727200,0],[1377730800,0],[1377734400,0],[1377738000,0],[1377741600,0],[1377745200,0],[1377748800,0], [1377752400,0],[1377756000,0],[1377759600,0],[1377763200,0],[1377766800,0],[1377770400,0]]
};
Create an array of series like:
var series = [];
$.each(jsonObj, function (key, val) {
var serie = {};
serie.label = key;
serie.data = val;
series.push(serie);
});
And then create the plot:
$.plot(
$("#placeholder"),
series,
{}
);
Fiddle here.