Set Additional Data to highcharts series - javascript
is there any way to pass some additional data to the series object that will use to show in the chart 'tooltip'?
for example
tooltip: {
formatter: function() {
return '<b>'+ this.series.name +'</b><br/>'+
Highcharts.dateFormat('%b %e', this.x) +': '+ this.y;
}
here we can only use series.name , this.x & this.y to the series. lets say i need to pass another dynamic value alone with the data set and can access via series object. is this possible?
Thank you all in advance.
Yes, if you set up the series object like the following, where each data point is a hash, then you can pass extra values:
new Highcharts.Chart( {
...,
series: [ {
name: 'Foo',
data: [
{
y : 3,
myData : 'firstPoint'
},
{
y : 7,
myData : 'secondPoint'
},
{
y : 1,
myData : 'thirdPoint'
}
]
} ]
} );
In your tooltip you can access it via the "point" attribute of the object passed in:
tooltip: {
formatter: function() {
return 'Extra data: <b>' + this.point.myData + '</b>';
}
}
Full example here: https://jsfiddle.net/burwelldesigns/jeoL5y7s/
Additionally, with this solution, you can even put multiple data as much as you want :
tooltip: {
formatter: function () {
return 'Extra data: <b>' + this.point.myData + '</b><br> Another Data: <b>' + this.point.myOtherData + '</b>';
}
},
series: [{
name: 'Foo',
data: [{
y: 3,
myData: 'firstPoint',
myOtherData: 'Other first data'
}, {
y: 7,
myData: 'secondPoint',
myOtherData: 'Other second data'
}, {
y: 1,
myData: 'thirdPoint',
myOtherData: 'Other third data'
}]
}]
Thank you Nick.
For time series data, especially with enough data points to activate the turbo threshold, the proposed solutions above will not work. In the case of the turbo threshold, this is because Highcarts expects the data points to be an array like:
series: [{
name: 'Numbers over the course of time',
data: [
[1515059819853, 1],
[1515059838069, 2],
[1515059838080, 3],
// you get the idea
]
}]
In order not to lose the benefits of the turbo threshold (which is important when dealing with lots of data points), I store the data outside of the chart and look up the data point in the tooltip formatter function. Here's an example:
const chartData = [
{ timestamp: 1515059819853, value: 1, somethingElse: 'foo'},
{ timestamp: 1515059838069, value: 2, somethingElse: 'bar'},
{ timestamp: 1515059838080, value: 3, somethingElse: 'baz'},
// you get the idea
]
const Chart = Highcharts.stockChart(myChart, {
// ...options
tooltip: {
formatter () {
// this.point.x is the timestamp in my original chartData array
const pointData = chartData.find(row => row.timestamp === this.point.x)
console.log(pointData.somethingElse)
}
},
series: [{
name: 'Numbers over the course of time',
// restructure the data as an array as Highcharts expects it
// array index 0 is the x value, index 1 is the y value in the chart
data: chartData.map(row => [row.timestamp, row.value])
}]
})
This approach will work for all chart types.
I am using AJAX to get my data from SQL Server, then I prepare a js array that is used as the data in my chart.
JavaScript code once the AJAX is successfull:
...,
success: function (data) {
var fseries = [];
var series = [];
for (var arr in data) {
for (var i in data[arr]['data'] ){
var d = data[arr]['data'][i];
//if (i < 5) alert("d.method = " + d.method);
var serie = {x:Date.parse(d.Value), y:d.Item, method:d.method };
series.push(serie);
}
fseries.push({name: data[arr]['name'], data: series, location: data[arr]['location']});
series = [];
};
DrawChart(fseries);
},
Now to show extra meta-data in the tooltip:
...
tooltip: {
xDateFormat: '%m/%d/%y',
headerFormat: '<b>{series.name}</b><br>',
pointFormat: 'Method: {point.method}<br>Date: {point.x:%m/%d/%y } <br>Reading: {point.y:,.2f}',
shared: false,
},
I use a DataRow to iterate through my result set, then I use a class to assign the values prior to passing back in Json format. Here is the C# code in the controller action called by Ajax.
public JsonResult ChartData(string dataSource, string locationType, string[] locations, string[] methods, string fromDate, string toDate, string[] lstParams)
{
List<Dictionary<string, object>> dataResult = new List<Dictionary<string, object>>();
Dictionary<string, object> aSeries = new Dictionary<string, object>();
string currParam = string.Empty;
lstParams = (lstParams == null) ? new string[1] : lstParams;
foreach (DataRow dr in GetChartData(dataSource, locationType, locations, methods, fromDate, toDate, lstParams).Rows)
{
if (currParam != dr[1].ToString())
{
if (!String.IsNullOrEmpty(currParam)) //A new Standard Parameter is read and add to dataResult. Skips first record.
{
Dictionary<string, object> bSeries = new Dictionary<string, object>(aSeries); //Required else when clearing out aSeries, dataResult values are also cleared
dataResult.Add(bSeries);
aSeries.Clear();
}
currParam = dr[1].ToString();
aSeries["name"] = cParam;
aSeries["data"] = new List<ChartDataModel>();
aSeries["location"] = dr[0].ToString();
}
ChartDataModel lst = new ChartDataModel();
lst.Value = Convert.ToDateTime(dr[3]).ToShortDateString();
lst.Item = Convert.ToDouble(dr[2]);
lst.method = dr[4].ToString();
((List<ChartDataModel>)aSeries["data"]).Add(lst);
}
dataResult.Add(aSeries);
var result = Json(dataResult.ToList(), JsonRequestBehavior.AllowGet); //used to debug final dataResult before returning to AJAX call.
return result;
}
I realize there is a more efficient and acceptable way to code in C# but I inherited the project.
Just to add some kind of dynamism :
Did this for generating data for a stacked column chart with 10 categories.
I wanted to have for each category 4 data series and wanted to display additional information (image, question, distractor and expected answer) for each of the data series :
<?php
while($n<=10)
{
$data1[]=array(
"y"=>$nber1,
"img"=>$image1,
"ques"=>$ques,
"distractor"=>$distractor1,
"answer"=>$ans
);
$data2[]=array(
"y"=>$nber2,
"img"=>$image2,
"ques"=>$ques,
"distractor"=>$distractor2,
"answer"=>$ans
);
$data3[]=array(
"y"=>$nber3,
"img"=>$image3,
"ques"=>$ques,
"distractor"=>$distractor3,
"answer"=>$ans
);
$data4[]=array(
"y"=>$nber4,
"img"=>$image4,
"ques"=>$ques,
"distractor"=>$distractor4,
"answer"=>$ans
);
}
// Then convert the data into data series:
$mydata[]=array(
"name"=>"Distractor #1",
"data"=>$data1,
"stack"=>"Distractor #1"
);
$mydata[]=array(
"name"=>"Distractor #2",
"data"=>$data2,
"stack"=>"Distractor #2"
);
$mydata[]=array(
"name"=>"Distractor #3",
"data"=>$data3,
"stack"=>"Distractor #3"
);
$mydata[]=array(
"name"=>"Distractor #4",
"data"=>$data4,
"stack"=>"Distractor #4"
);
?>
In the highcharts section:
var mydata=<? echo json_encode($mydata)?>;
// Tooltip section
tooltip: {
useHTML: true,
formatter: function() {
return 'Question ID: <b>'+ this.x +'</b><br/>'+
'Question: <b>'+ this.point.ques +'</b><br/>'+
this.series.name+'<br> Total attempts: '+ this.y +'<br/>'+
"<img src=\"images/"+ this.point.img +"\" width=\"100px\" height=\"50px\"/><br>"+
'Distractor: <b>'+ this.point.distractor +'</b><br/>'+
'Expected answer: <b>'+ this.point.answer +'</b><br/>';
}
},
// Series section of the highcharts
series: mydata
// For the category section, just prepare an array of elements and assign to the category variable as the way I did it on series.
Hope it helps someone.
Related
how to get arrays inside objects , remove double quotes and make it as an object to put inside json syntax
i make jsonstring like this: { "dataTarget":["[Date.UTC(2016,3,01),10.00]", "[Date.UTC(2016,1,01),5.00]"], "dataRealisasi" :["[Date.UTC(2016,3,01),10.00]", "[Date.UTC(2016,1,01),5.00]"] } i retrieve it thru jquery ajax and parse it var dataChart = JSON.parse(msg.d); var dataTarget = dataChart['dataTarget'] var dataRealisasi = dataChart['dataRealisasi'] i console log dataTarget , this is the result : ["[Date.UTC(2016,3,01),10.00]", "[Date.UTC(2016,1,01),5.00]"] what i need is a variable that is like this [ [Date.UTC(2016,3,01),10.00], [Date.UTC(2016,1,01),5.00] ] which i can pass it as a variable into this $('#container3').highcharts({ chart: { type: 'spline' }, title: { text: 'Monitoring Proyek' }, subtitle: { text: 'Proyek' }, xAxis: { type: 'datetime', dateTimeLabelFormats: { // don't display the dummy year month: '%e. %b', year: '%b' }, title: { text: 'Date' } }, yAxis: { title: { text: 'Target (%)' }, min: 0 }, tooltip: { headerFormat: '<b>{series.name}</b><br>', pointFormat: '{point.x:%e. %b}: {point.y:.2f} %' }, plotOptions: { spline: { marker: { enabled: true } } }, series: [{ "name": "Proyeksi Target", "data": dataTarget // this is the variable }, { name: 'Realisasi', data: dataRealisasi // this is the variable }] }); update: the problem is when i create json string without the double quote then JSON.parse it returns error... i already change the server side function and return object : [["Date.UTC(2016,3,01)",10.00], ["Date.UTC(2016,1,01)",5.00]] , now i need to remove the the double quotes and change it too : [[Date.UTC(2016,3,01),10.00], [Date.UTC(2016,1,01),5.00]] need help here...
You can transform json like this (do not use eval): [ "[Date.UTC(2016,3,01),10.00]", "[Date.UTC(2016,1,01),5.00]" ].map(function(v){ return new Function('return ' + v)(); }); but strongly recommend you just use the timestamp, because this transform is have a bit more cost then as usual
Don't know about the leading 0 so I would clean that off // the data var data = [ "[Date.UTC(2016,3,01),10.00]", "[Date.UTC(2016,1,01),5.00]" ]; var clean = function(n){ // remove leadin zero as we want the numbers. return Number(n.replace(/^0+?/, "")); } // removes unneeded characters "Date.UTC(", ")","[","]" // split to an array of strings. Clean of leading zeros ? and convert to numbers var convert = function(str){ var n = str.replace(/Date.UTC\(|\)|\[|\]/g, "").split(",").map(clean); return [Date.UTC(n[0], n[1], n[2]), n[3]]; // get date and return the array item as an array } // Start the ball rolling. try{ data = data.map(convert); }catch(e){ console.log("You are having a bad day!"); } // data === [[1459468800000, 10], [1454284800000, 5]];
How to plot a highstock single line series graph from ajax data
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.
JS for Loop in Flot with JSON 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.
problem with highcharts series option
Hi i am having problem with my highcharts 'series' options. i initialized the chart options as below: var options = { chart: { renderTo: 'chart', defaultSeriesType: 'line', }, title: { text: 'Weight Monitor', }, xAxis: { title: { text: 'Date Measurement' }, categories: [] }, yAxis: { title: { text: 'Weight (in Lbs)' } }, series: [] }; I kept the categories: [] blank so that i can put the values in categories later. Same thing i did with my series options. I kept the data:[] as blank to fill it later. Now i wrote the code to fill the data. var lines = [ [2011,150], [2012,121], $.each(lines, function(lineNo, line) { var items = line.toString().split(","); $.each (items, function(itemNo, item) { if(itemNo == 0){ alert("itemNo: " + itemNo + " item: " + item); options.xAxis.categories.push(item); alert(options.xAxis.categories); } else { var series = { data: [] }; alert("itemNo: " + itemNo + " item: " + item); options.series.data.push(parseFloat(item)); alert(options.series.data); }; }); }); var chart = new Highcharts.Chart(options); Now when i execute this code, my categories[] is getting values properly, but the execution gets stuck when it is at "options.series.data.push(parseFloat(item))". I am getting the proper value in the "alert("itemNo: " + itemNo + " item: " + item);". but just after that it hangs while pushing the item in series.data[] any idea what is the problem. and i am running this javascript in php project so don't know if there is any issue because of the language. thanks
The problem is options.series.data.push(parseFloat(item)). If you look at your options object, you can see that your series array is empty. You can ad series object in your options definition as follows - series: [{ data: [] }] Also the line var series = { data: [] }; is of no use.
string passed does not render chart object, but string value if pasted into javascript directly does. Highcharts
On debug. when execution is leaving the controller I debug and the variable contains : ?sArray {string[17, 2]} [0, 0]: "Arecleoch" [0, 1]: "21" [1, 0]: "Barnesmore" [1, 1]: "3" etc etc.... then in the javascript its received as : ?sdata {...} [0]: "Arecleoch" [1]: "21" [2]: "Barnesmore" [3]: "3" [4]: "Beinn An Tuirc" [5]: "1" [6]: "Beinn An Tuirc Phase 2" etc so the pie is displayed as one solid circle of colour puzzled, any ideas? controller code below : public JsonResult GetChartData_IncidentsBySite() { var allSites = _securityRepository.FindAllSites(); var qry = from s in _db.Sites join i in _db.Incidents on s.SiteId equals i.SiteId group s by s.SiteDescription into grp select new { Site = grp.Key, Count = grp.Count() }; string[,] sArray = new string[qry.Count(),2]; int y = 0; foreach (var row in qry.OrderBy(x => x.Site)) { if ((row.Count > 0) && (row.Site != null)) { sArray[y, 0] = row.Site.ToString(); sArray[y, 1] = row.Count.ToString(); y++; } } return Json(sArray , JsonRequestBehavior.AllowGet); } Here is the javascript code : $.getJSON(url, null, function(sdata) { debugger; chart = new Highcharts.Chart({ chart: { renderTo: 'container', plotBackgroundColor: null, plotBorderWidth: null, plotShadow: false }, title: { text: 'Number of Environmental Incidents by Site' }, tooltip: { formatter: function() { return '<b>' + this.point.name + '</b>: ' + this.y + ' %'; } }, plotOptions: { pie: { allowPointSelect: true, cursor: 'pointer', dataLabels: { enabled: false }, showInLegend: true } }, series: [{ type: 'pie', name: 'Incidents by Site', data: sdata }] }); }); });
In the version that works, data is an Array of Arrays of String ; data: [["Arecleoch",21], ... (Notice there is no oppening quotes before the first bracket). In the version that does not work, it is a String representing the Array. I suspect the charts API only expect an Array (in this case, an array of array, actually). So it depends on what this does : $.getJSON(url, null, function(data) { // What is the type of data here ? From your controller and the display of your debugger, I think data is itself an Array of Arrays. You should directly pass it to the charts API (without the sData = data.toString()) function wich actually transforms the Array ['a', 'b', 'c'] into a String representing the array, like "['a', 'b', 'c']"); // Callback parameter renamed to show it is an Array of Arrays $.getJSON(url, null, function(aaData) { // ... skipped ... series: [{ type: 'pie', name: 'Incidents by Site', data: aaData /* Use the Array itself */ }] Edit : my solution will only work if the controller output something like : { data : [[ "Arecleoch", 21], ["Whatever", 42]] } However it seems like your controller returns something like { data : "[['Arecleoch', 21],['Whatever', 42]]" } (Maybe without the { data : } part, I don't know if you need a top-level element or if you are derectly returning the Array in JSON) Is that the case ? If so, then you'll have to either : change the controller parse the string on the client side, in javascript