Flot Chart : Adding Checkbox's to Toggle Chart Series - javascript

After setting up my first chart I'm looking to add check-boxs to toggle which series are selected.
Flot provides an example here : http://www.flotcharts.org/flot/examples/series-toggle/
Now when i tried to replicate this I'm getting error: 'datasets' is undefined could anyone explain why??
Also bonus points if anyone can tell my why the legend still display's inside the graph?
Chart Looks like :
View Code :
<div class="legend-container"></div>
<div class="graph-container">
<div id="placeholder" class="graph-placeholder"></div>
</div>
<p id="choices"></p>
Chart Code:
$(document).ready(function fetchData() {
function onDataReceived(series)
{
console.log('recieved data now parsing the data');
var currentdata = $.parseJSON(series);
//Testing
console.log(currentdata);
console.log("series sub-arrays");
console.log(currentdata[0]);
console.log(currentdata[1]);
console.log(currentdata[2]);
var datasets = [
{
label: "Current_Out",
data: currentdata[0],
yaxis: 2,
color: '#00C932',
points: { fillColor: "#00C932", show: true },
lines: { show: true }
}, {
label: "Temperature",
data: currentdata[1],
yaxis: 1,
color: "#0062FF",
points: { fillColor: "#0062FF", show: true },
lines: {show:true }
}]
var options = {
legend: {
show: true,
placement: 'outsideGrid',
container: $("#legend-container")
},
lines: {
show: true,
fill: false,
},
axisLabels: {
show: true
},
xaxes: [{
mode: "time",
timeformat: "%H:%M:%S",
axisLabel:'Date',
axisLabelUseCanvas: false,
axisLabelFontSizePixels: 12,
axisLabelFontFamily: 'Verdana, Arial, Helvetica, Tahoma, sans-serif',
axisLabelPadding: 5
}],
yaxes: [{
position: "left",
axisLabel:'Celcius',
axisLabelUseCanvas: true,
axisLabelFontSizePixels: 12,
axisLabelFontFamily: 'Verdana, Arial, Helvetica, Tahoma, sans-serif',
axisLabelPadding: 5
}, {
position: "right",
axisLabel: 'mA'
}],
grid: {
hoverable: true,
clickable: true,
borderWidth: 1
},
legend: {
labelBoxBorderColor: "none",
position: "right"
},
points: {
show: true,
fillColor: "#000000"
}
};
$.plot($("#placeholder"), datasets, options);
}
$.ajax({
url: '/Ajax/GetGraphData',
type: "GET",
dataType: "json",
success: onDataReceived,
failure: function() {
console.log('Fail!');
}
});
Jquery for Checkbox's
// insert checkboxes
var choiceContainer = $("#choices");
$.each(datasets, function (key, val) {
choiceContainer.append('<br/><input type="checkbox" name="' + key +
'" checked="checked" id="id' + key + '">' +
'<label for="id' + key + '">'
+ val.label + '</label>');
});
choiceContainer.find("input").click(plotAccordingToChoices);
function plotAccordingToChoices() {
var data = [];
choiceContainer.find("input:checked").each(function () {
var key = $(this).attr("name");
if (key && datasets[key])
data.push(datasets[key]);
});
if (data.length > 0)
$.plot($("#placeholder"), data, {
yaxis: { min: 0 },
xaxis: { tickDecimals: 0 }
});
}
plotAccordingToChoices();

Scoping issue. var datasets is local to the onDataReceived function. It is not accessible outside that function. Initing it to null in the $(document).ready( handler should make it accessible to everything in that scope.
As for your second question, you need to show us the CSS attached to those divs. I'm guessing your graph-container is absoluting positioned. Also, in your options, you have two different configurations for legend. Delete the second one.

Related

How to contain category data in tooltip

I've seen tutorials and posts about getting data from the x axis into the tooltip but I am overriding it with categories and cannot figure out how to get the x axis to show up in the tooltip.
This is what im working with:
function showTooltip(x, y, contents) {
$('<div id="tooltip" class="flot-tooltip tooltip"><div class="tooltip-arrow"></div>' + contents + '</div>').css({
top: y - 43,
left: x - 15,
}).appendTo("body").fadeIn(200);
}
var data = [[1492854610, -1240],[1492939020, -1273],[1493025073, -1279],[1493117066, -1186],[1493198484, -1269],[1493289175, -1198],[1493370646, -1280],[1493458518, -1255],[1493543731, -1275],[1493630250, -1273],[1493716306, -1279],[1493803609, -1264],[1493889258, -1276],[1493975557, -1278],[1494064529, -1235],[1494155440, -1160],[1494237980, -1224],[1494321047, -1280],[1494407990, -1271],[1494494125, -1275],[1494581609, -1257],[1494668321, -1252],[1494753220, -1277],[1494847855, -1140],[1494925963, -1278],[1495012537, -1275],[1495099289, -1269],[1495188205, -1227],[1495273568, -1244],[1495358329, -1272]];
$.plot($("#placeholder"), [{
label: "Delay: ",
data: data,
color: "#3a8ce5"
}], {
xaxis: {
mode: "categories",
tickLength: 0,
ticks: [[0, "1:50 AM"],[1, "1:17 AM"],[2, "1:11 AM"],[3, "2:44 AM"],[4, "1:21 AM"],[5, "2:32 AM"],[6, "1:10 AM"],[7, "1:35 AM"],[8, "1:15 AM"],[9, "1:17 AM"],[10, "1:11 AM"],[11, "1:26 AM"],[12, "1:14 AM"],[13, "1:12 AM"],[14, "1:55 AM"],[15, "3:10 AM"],[16, "2:06 AM"],[17, "1:10 AM"],[18, "1:19 AM"],[19, "1:15 AM"],[20, "1:33 AM"],[21, "1:38 AM"],[22, "1:13 AM"],[23, "3:30 AM"],[24, "1:12 AM"],[25, "1:15 AM"],[26, "1:21 AM"],[27, "2:03 AM"],[28, "1:46 AM"],[29, "1:18 AM"]]
},
yaxis: {
min: -2000,
max: 1000,
},
series: {
lines: {
show: true,
fill: true
},
points: {
show: true,
}
},
grid: {
hoverable: true,
clickable: true,
markings: [
{ color: '#000', lineWidth: 1, yaxis: { from: 0, to: 0 } },
]
},
legend: {
show: false
}
});
$("#placeholder").bind("plothover", function(event, pos, item) {
if (item) {
if (previousPoint != item.dataIndex) {
previousPoint = item.dataIndex;
$("#tooltip").remove();
var y = item.datapoint[1].toFixed();
showTooltip(item.pageX, item.pageY,
item.series.label + " = " + y);
}
} else {
$("#tooltip").remove();
previousPoint = null;
}
});
I am trying to get the times part of the categories. The item array has 3 pieces of data, none of which are the times
jFiddle:
http://jsfiddle.net/zw14y8c3/2/
The item.datapoint[0] data has the index of the x-axis tick. With that you can get the actual tick label from the ticks array:
var x = $("#placeholder").data('plot').getAxes().xaxis.ticks[item.datapoint[0]].label;
See the updated fiddle for the full example.

Have an issue with JavaScript, AJAX code displaying data

I need some tips from you out there to come over a good solution on my problem with JavaScript, AJAX and JSON data. I want to fill a generic set with barcharts (I am using HighCharts) on my web page. The data is in JSON format which from the start I only used date and value as pair data set. The solution works fine of I had only one bar chart it, but I have a lot of charts on my page and I need to show all of them (up to twelve).
Now I want to adjust for displaying more than one graph. In the code below the DataMacro array works fine with the chart. It also has a hard coded ID matching a . Now I have a series of in the page like id=barchart11, id=barchar21, and so on. In the dataset I have made a tag called PanelCodeUI that I am going to use looping through the dataset. The problem is how to do that. The each-loop will now fill in all date,value for all vessels.
And further it I need to restructure the function which is displaying the barchart. The best thing would be to call a function with a data array and panelCodeUI id just replacing the name of the barchart and set in the datamacro as is. But I don’t know how to do this. The data is mixed between all vessels and I need to collect all data before sending to a function. So is the problem with AJAX and JavaScript with is asynchron. I need to ensure that it behaves correctly and fast.
Maybe I need to change my dataset, or I need to do this in several step like finding all vessel IDs then do another AJAX call to get date,value pair from a vessel and then displaying. I hope there is a way to do this with this data set and hope somebody can help me on this
Here is a bit of the JSON data set:
[
{"__type":"Demo.Entities.OilProductionLast5DaysEntity","Date":1465084800000,"Value":844,"VesselId":1,"SectorId":2,"PanelCodeUI":"21","VesselCodeUI":"21","VesselSorting":1},
{"__type":"Demo.Entities.OilProductionLast5DaysEntity","Date":1465084800000,"Value":8720,"VesselId":4,"SectorId":1,"PanelCodeUI":"11","VesselCodeUI":"12","VesselSorting":2},
{"__type":"Demo.Entities.OilProductionLast5DaysEntity","Date":1465084800000,"Value":948,"VesselId":5,"SectorId":1,"PanelCodeUI":"11","VesselCodeUI":"11","VesselSorting":1},
{"__type":"Demo.Entities.OilProductionLast5DaysEntity","Date":1465084800000,"Value":0,"VesselId":6,"SectorId":3,"PanelCodeUI":"31","VesselCodeUI":"31","VesselSorting":1},
{"__type":"Demo.Entities.OilProductionLast5DaysEntity","Date":1465171200000,"Value":2067,"VesselId":1,"SectorId":2,"PanelCodeUI":"21","VesselCodeUI":"21","VesselSorting":1}
]
And here is the JavaScript code so far:
$(function () {
var datamacro = [];
$.ajax({
type: "POST",
url: '../Services/HighChartService.asmx/GetOilProductionLast5DaysByActiveVessels',
data: '',
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (seriedata) {
console.log(JSON.stringify(seriedata.d));
var productions = seriedata.d;
$.each(productions, function (index, productions) {
var yval = productions.Value;
var xval = productions.Date;
var x = [xval, yval];
datamacro.push(x);
//alert("productions Name: " + productions.Date + "\nID: " + productions.Value);
});
$(function () {
//var bchart = '#barchart' + vesselindex.toString();
// want this to be looped with generic names like #barchart11, #barchart21, #barchart31 and so on
$('#barchart11').highcharts({
chart: {
type: 'column'
},
title: {
text: 'LAST FIVE DAYS'
},
subtitle: {
text: ''
},
xAxis: {
type: "datetime",
tickInterval: 24 * 3600 * 1000,
labels: {
rotation: -45,
align: 'right'
},
dateTimeLabelFormats: { // don't display the dummy year
day: '%e. %b',
},
//crosshair: true
},
credits: {
enabled: false
},
yAxis: {
labels: {
enabled: false
},
title: {
text: null
}
},
tooltip: {
formatter: function () {
return Highcharts.dateFormat('%d/%m/%Y', new Date(this.x)) + '<br/>' + ' in barrels: ' + this.y;
}
},
plotOptions: {
column: {
pointPadding: 0.2,
borderWidth: 0
}, series: {
pointRange: 24 * 3600 * 1000, // one day
pointInterval: 3600 * 1000
}
},
series: [{
//name: '',
showInLegend: false,
data: datamacro,
dataLabels: {
enabled: true,
rotation: -90,
color: '#FFFFFF',
align: 'right',
format: '{point.y:.1f}', // one decimal
y: 10, // 10 pixels down from the top
style: {
fontSize: '13px',
fontFamily: 'Verdana, sans-serif'
}
}
}]
});
});
},
error: function (r) {
alert(r.responseText);
},
failure: function (r) {
alert(r.responseText);
}
});
});
If i understand correctly, you would like to draw a chart for each different panelCodeUI ?
If that's the case, change your code after AJAX success with that :
var productions = seriedata.d;
var listPanelCodeUI = productions.map(function(p){return p.PanelCodeUI}).filter(function(item, pos, self) {
return self.indexOf(item) == pos;
});
//listPanelCodeUI : [21,11,31]
listPanelCodeUI.sort();
listPanelCodeUI.forEach(function(e){
datamacro = [];
//Create a div for each panelCodeUI
$("body").append("<div id='barchart" + e + "'></div>");
var divId = "#barchart"+e;
//Filter productions for specific panelCodeUI
var data = productions.filter(function(p){return p.panelCodeUI === e});
data.forEach(function(d){
var yval = d.Value;
var xval = d.Date;
var x = [xval, yval];
datamacro.push(x);
});
$(function () {
$(divId).highcharts({
...
})
})
}
That's what you need to parse your data:
charts = [];
$.each(productions.map(function(el) {
return el.PanelCodeUI;
}).filter(function(el, index, arr) {
return arr.indexOf(el) === index;
}), function(index,PanelCodeUI) {
var serie = productions.filter(function(el) {
return el.PanelCodeUI === PanelCodeUI;
});
$.each(serie, function(index, production) {
datamacro.push([production.Value, production.Date]);
});
drawChart('#barchart' + PanelCodeUI, 'LAST FIVE DAYS', datamacro);
});
Also i made this helper function to create the charts:
function drawChart(containerID, chartTitle, data) {
charts.push(new Highchart.Chart({
chart: {
type: 'column',
renderTo: containerID
},
title: {
text: chartTitle
},
subtitle: {
text: ''
},
xAxis: {
type: "datetime",
tickInterval: 24 * 3600 * 1000,
labels: {
rotation: -45,
align: 'right'
},
dateTimeLabelFormats: { // don't display the dummy year
day: '%e. %b',
},
//crosshair: true
},
credits: {
enabled: false
},
yAxis: {
labels: {
enabled: false
},
title: {
text: null
}
},
tooltip: {
formatter: function() {
return Highcharts.dateFormat('%d/%m/%Y', new Date(this.x)) + '<br/>' + ' in barrels: ' + this.y;
}
},
plotOptions: {
column: {
pointPadding: 0.2,
borderWidth: 0
},
series: {
pointRange: 24 * 3600 * 1000, // one day
pointInterval: 3600 * 1000
}
},
series: [{
//name: '',
showInLegend: false,
data: data,
dataLabels: {
enabled: true,
rotation: -90,
color: '#FFFFFF',
align: 'right',
format: '{point.y:.1f}', // one decimal
y: 10, // 10 pixels down from the top
style: {
fontSize: '13px',
fontFamily: 'Verdana, sans-serif'
}
}
}]
}));
}

Flot Categories Plugin Ordering Incorrect

Thanks in advance for your time.
I have the following code for a Flot Chart
<script src="js/plugins/flot/jquery.flot.js"></script>
<script src="js/plugins/flot/jquery.flot.tooltip.min.js"></script>
<script src="js/plugins/flot/jquery.flot.spline.js"></script>
<script src="js/plugins/flot/jquery.flot.resize.js"></script>
<script src="js/plugins/flot/jquery.flot.categories.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$(function() {
var data = [{
"label": "Commission",
"color": "#1ab394",
"data": [["Oct", ],["Nov", ],["Dec", ],["Jan", ],["Feb", ],["Mar", ],["Apr", ],["May", 14],["Jun", 0],["Jul", 5],["Aug", 12],["Sep", 7]]
}, {
"label": "EPL",
"color": "#1C84C6",
"data": [["Oct", 0],["Nov", 0],["Dec", 0],["Jan", 0],["Feb", 0],["Mar", 0],["Apr", 0],["May", 1.75],["Jun", 0.00],["Jul", 0.17],["Aug", 0.39],["Sep", 0.35]]
}];
var options = {
series: {
lines: {
show: false,
fill: true
},
splines: {
show: true,
tension: 0.4,
lineWidth: 1,
fill: 0.4
},
points: {
radius: 0,
show: true
},
shadowSize: 2
},
grid: {
borderColor: '#eee',
borderWidth: 1,
hoverable: true,
backgroundColor: '#fff'
},
tooltip: true,
tooltipOpts: {
content: function (label, x, y) { return x + ' : ' + y; }
},
xaxis: {
tickColor: '#eee',
mode: 'categories'
},
yaxis: {
tickColor: '#eee'
},
shadowSize: 0
};
var chart = $('.dashchart');
if(chart.length)
$.plot(chart, data, options);
});
})(window, document, window.jQuery);
</script>
The docs state...
By default, the labels are ordered as they are met in the data series.
If you need a different ordering, you can specify "categories" on the
axis options and list the categories there:
https://code.google.com/p/flot/source/browse/trunk/jquery.flot.categories.js?r=341
However the x axis ordering is not the same as the data series, as seen in the screenshot below
Any idea why this may be.
I figured this out. Hope it helps someone some day
Seems Flot doesnt like empty values in the data series
"data": [["Oct", ],["Nov", ],["Dec", ],["Jan", ],["Feb", ],["Mar", ],["Apr", ],["May", 14],["Jun", 0],["Jul", 5],["Aug", 12],["Sep", 7]]
changed to this and it works fine
"data": [["Oct", 0],["Nov", 0],["Dec", 0],["Jan", 0],["Feb", 0],["Mar", ]0,["Apr", 0],["May", 14],["Jun", 0],["Jul", 5],["Aug", 12],["Sep", 7]]

how do you do ajax call in javascript

I am building a dashboard that will have buttons on top for monthly, weekly and real time data.
<div class="zoom_controls">
<a class="profile" id="monthly_data" href="#" data-chart="line" data-range="6m">Monthly</a>
<a class="profile" id="weekly_data"href="#" data-chart="line" data-range="3m">Weekly</a>
<a class="profile" id="real_time" href="#" data-chart="line" data-range="1m">Real Time</a>
</div>
<div class="main" id="chart" style="width:700px; height:300px;"></div>
This is the javascript that calls a php file to get the data and insert it into highcharts:
function cpu_current() {
//current_cpu_data.php retrieves the data from a flat file
$.getJSON('current_cpu_data.php', function(data) {
var chart = new Highcharts.StockChart({
chart: {
borderColor: '#98AFC7',
borderRadius: 20,
borderWidth: 1,
renderTo: 'chart',
type: 'line',
marginRight: 10,
zoomType: 'x'
},
exporting: {
enabled: true
},
legend: {
enabled: true,
backgroundColor: '#FCFFC5',
borderColor: 'black',
borderWidth: 2,
width: 500,
shadow: true
},
plotOptions: {
series: {
lineWidth:1
}
},
rangeSelector: {
enabled:false
},
scrollbar: {
enabled: false
},
navigator : {
enabled : false
},
xAxis: {
gridLineColor: '#EEEEEE',
gridLineWidth: 1
},
yAxis: { // Primary yAxis
labels: {
style: {
color: 'blue'
}
},
gridLineColor: '#EEEEEE',
gridLineWidth: 0,
tickInterval: 20,
min:0,
max:100,
plotLines : [{
value : 70,
color : '#FF3300',
dashStyle : 'line',
width : 1,
label : {
text : 'Threshold=70%',
align: 'right',
style: {
fontWeight: 'bold'
}
}
}],
title: {
text: '% CPU Utilization',
style: {
color: 'blue'
}
}
},
credits: {
enabled: false
},
title: {
text: 'CPU',
style: {
color: '#333000',
fontSize: '14px'
}
},
subtitle: {
text: '10 minute peaks in last 24 hours'
},
tooltip: {
pointFormat: '<span style="color:{series.color}">{series.name}</span>: <b>{point.y} </b><br>',
valueDecimals: 2
},
series:data
});
});
}
Here I can use jquery click event to switch between different tabs:
$("#monthly_data").click(function() {
hmms_cpu_current();
});
$("#weekly_data").click(function() {
hmms_cpu_weekly();
});
$("#real_time").click(function() {
cpu_current();
});
My question is this, when the user only interested in real_time and clicks and leaves it there, I need cpu_current() to update on its own via ajax calls. If a user clicks on monthly_data and leaves it there cpu_current() need to stop.
How would do this given the above code?
if you are using MVC Model you can use Ajax like this using onclick method of particular javascript function ,
<script type="text/javascript">
function hmms_cpu_current() {
$.ajax({
type: 'GET',
async: false,
url: 'yourcontroller/youraction',
contentType: "application/json; charset=utf-8",
dataType: 'json',
success: function (data) {
var obj = $.parseJSON(data);
$.each(data, function (i, item) {
alert(item.text) // do your stuff with returned value
});
},
error: function () {
output.text('There was an error loading the data.');
}
});
}
I would add a Javascript Timer() or setTimeout() which re-sends the ajax call and updated the page.
You could also give the user the option of doing this and put it inside a Function.
If you give the Timer an ID, you can also stop and start it.
Modify all your functions to return a jqXHR like this:
function cpu_current() {
//$.getJSON return jqXHR, you could use it to abort ajax.
return $.getJSON('current_cpu_data.php', function(data) {
//All your code
}
The use abort in your event handlers:
var currentjqXHR;
$("#monthly_data").click(function() {
if (currentjqXHR){
currentjqXHR.abort();//abort current ajax
}
currentjqXHR = hmms_cpu_current();
});
$("#weekly_data").click(function() {
if (currentjqXHR){
currentjqXHR.abort();//abort current ajax
}
currentjqXHR = hmms_cpu_weekly();
});
$("#real_time").click(function() {
if (currentjqXHR){
currentjqXHR.abort();//abort current ajax
}
currentjqXHR = cpu_current();
});

SetData() not working on Change Event HighCharts Pie Chart

I'm looking for a way to dynamically update data in a highcharts pie chart based on the change event on a dropdownlist. I have seen a couple examples but I am really unable to figure out why I can't get this working. Here is my whole code, I wrap my stuff inside a function so I can call the function with the Change() event of the dropdownlist, but I get the error of CRIPT438: Object doesn't support property or method 'setData'
function showClass(){
var total = 0;
var options = {
chart:{type:'pie',
renderTo: 'ctl00_ContentPlaceHolder1_Overview1_tcAssetAllocation_body',
events: {
load: function(event) {
$('.highcharts-legend-item').last().append('<br/><div style="width:220px"><hr/> <span style="float:left"> Total </span><span style="float:right">100%</span> </div>')
}
}
},
credits:{enabled: false},
colors:[
'#5485BC', '#AA8C30', '#5C9384', '#981A37', '#FCB319', '#86A033', '#614931', '#00526F', '#594266', '#cb6828', '#aaaaab', '#a89375'
],
title:{text: null},
tooltip:{
enabled: true,
animation: true
},
plotOptions: {
pie: {
allowPointSelect: true,
animation: true,
cursor: 'pointer',
showInLegend: true,
dataLabels: {
enabled: false,
formatter: function() {
return this.percentage.toFixed(2) + '%';
}
}
}
},
legend: {
enabled: true,
layout: 'vertical',
align: 'right',
width: 220,
verticalAlign: 'top',
borderWidth: 0,
useHTML: true,
labelFormatter: function() {
total += this.y;
return '<div style="width:200px"><span style="float:left">' + this.name + '</span><span style="float:right">' + this.y + '%</span></div>';
},
title: {
text: 'Primary',
style: {
fontWeight: 'bold'
}
}
},
series: [{
type: 'pie',
data: [['Domestic Equity', 38.5],['International Equity', 26.85],['Other', 15.70],['Cash and Equivalents', 10.48],['Fixed Income', 8.48]]
}]
}
var chart = new Highcharts.Chart(options);
$("#ctl00_ContentPlaceHolder1_Overview1_AccountList1_ddlAccounts").change(function(){
var selVal = $("#ctl00_ContentPlaceHolder1_Overview1_AccountList1_ddlAccounts").val();
if(selVal == '1124042'){
chart.series[0].setData([['Domestic Equity', 18.5], ['International Equity', 46.85], ['Other', 5.70], ['Cash and Equivalents', 20.48], ['Fixed Income', 8.48]]); }
});
}
is it because i am nested inside another function? it's jsut that all the fiddles use the document.ready function and it loads properly calling the function in the document.ready() but getting it on the change event is messing with me.
Any help is greatly appreciated.
Tahnk you very much,
NickG
You are wrong to use object options as part of Highcharts API. Find that line: options.series[0].setData and change to chart.series[0].setData(). Then remove creating new chart ( you don't need that - chart is already created ).

Categories