Highcharts 2 groups of series - javascript

I want to display a chart (that takes the data from a PHP file with JSON) with two dimensions of series : the first one is the technology used (5 in total), and the other one is the export or import.
So when the user is on the page, he can choose to diplay the technology, as export, import or both.
In first, to join one technology import with the same in export, I have used a "linkedto=previous", the result is a single item in the legend per technology.
But I would like to add two items in the legend : "Import" and "Export", with 0 data, that would permit to display or not the import or the export.
I have used this code, but I can't find how to display the choice of import, export, the both, or nothing.
Thank you very much if you take a bit of time to read my post. BR
$(function () {
var chart;
$(document).ready(function() {
var options = {
chart: {
renderTo: 'euro',
type: 'column'
},
title: {
text: 'Vision en euro'
},
xAxis: {
categories: []
},
yAxis: {
title: {
text: 'k€'
},
stackLabels: {
enabled: true,
rotation: 30,
}
},
tooltip: {
headerFormat: '{point.x}<b></b><br/>',
},
plotOptions: {
column: {
stacking: 'normal',
dataLabels: {
enabled: false,
},
}
},
series: []
};
Highcharts.setOptions(Highcharts.theme);
$.getJSON('SOURCE.php', function(json) {
options.xAxis.categories = json[0]['month'];
options.series[0] = {};
options.series[0].name = 'TECHNO 1';
options.series[0].data = json[1]['data'];
options.series[0].stack ='EXPORT';
options.series[0].color= '#808080';
options.series[1] = {};
options.series[1].name = 'TECHNO 1';
options.series[1].data = json[0]['data'];
options.series[1].stack = 'IMPORT';
options.series[1].linkedTo = ':previous';
options.series[1].color= 'url(#highcharts-default-pattern-0)';
options.series[2] = {};
options.series[2].name = 'TECHNO 2';
options.series[2].data = json[3]['data'];
options.series[2].stack = 'EXPORT';
options.series[2].color= '#FFC125';
options.series[3] = {};
options.series[3].name = 'TECHNO 2';
options.series[3].data = json[2]['data'];
options.series[3].stack = 'IMPORT';
options.series[3].linkedTo = ':previous';
options.series[3].color= 'url(#highcharts-default-pattern-1)';
options.series[4] = {};
options.series[4].name = 'TECHNO 3';
options.series[4].data = json[5]['data'];
options.series[4].stack = 'EXPORT';
options.series[4].color= '#2B99FF';
options.series[5] = {};
options.series[5].name = 'TECHNO 3';
options.series[5].data = json[4]['data'];
options.series[5].stack = 'IMPORT';
options.series[5].linkedTo = ':previous';
options.series[5].color= 'url(#highcharts-default-pattern-2)';
options.series[6] = {};
options.series[6].name = 'TECHNO 4';
options.series[6].data = json[7]['data'];
options.series[6].stack = 'EXPORT';
options.series[6].color= '#C72828';
options.series[7] = {};
options.series[7].name = 'TECHNO 4';
options.series[7].data = json[6]['data'];
options.series[7].stack = 'IMPORT';
options.series[7].linkedTo = ':previous';
options.series[7].color= 'url(#highcharts-default-pattern-3)';
options.series[8] = {};
options.series[8].name = 'TECHNO 5';
options.series[8].data = json[9]['data'];
options.series[8].stack = 'Sortie';
options.series[8].color= '#1CA154';
options.series[9] = {};
options.series[9].name = 'TECHNO 5';
options.series[9].data = json[8]['data'];
options.series[9].stack = 'EXPORT';
options.series[9].linkedTo = ':previous';
options.series[9].color= 'url(#highcharts-default-pattern-4)';
options.series[10] = {};
options.series[10].name = 'IMPORT';
options.series[10].data = json[10]['data'];
options.series[10].stack = 'IMPORT';
options.series[10].color= 'url(#highcharts-default-pattern-5)';
options.series[11] = {};
options.series[11].name = 'EXPORT';
options.series[11].data = json[11]['data'];
options.series[11].stack = 'IMPORT';
options.series[11].color= 'url(#highcharts-default-pattern-5)';
//options.series[1].color= '#C89B9B';
chart = new Highcharts.Chart(options);
});
});
});

First of all, you can hide or show a series in a chart by modifying the "visible" property of a series object to false or true respectively. For example:
options.series[10].visible = true; // or false
Secondly, you can achieve that in an event listener (the push of a button for example), using chart.update() method, and passing the changes as an argument. Have a look in here: Dynamic charts -> update options after render.
But the simplest solution is to just repeat the
chart = new Highcharts.Chart(options);
statement, after you have put in the series object the "visible" property with the value you like, for each series (import/export) you want to show or hide.
Finally, having 2 kinds of clickable labels in the legend can only be done with some custom jquery programming of your own. I think a couple of small buttons next to the chart would be much easier and faster to implement.

Related

CanvasJS not properly rendering chart

I am using the following code to render an OHLC chart in CanvasJS:
<script>
var candleData = [];
var chart = new CanvasJS.Chart("chartContainer", {
title: {
text: 'Demo Stacker Candlestick Chart (Realtime)'
},
zoomEnabled: true,
axisY: {
includeZero: false,
title: 'Price',
prefix: '$'
},
axisX: {
interval: 1,
},
data: [{
type: 'ohlc',
dataPoints: candleData
}
]
});
function mapDataToPointObject(data) {
var dataPoints = [];
for(var i = 0; i < data.length; i++) {
var obj = data[i];
var newObj = {
x: new Date(obj.time),
y: [
obj.open,
obj.high,
obj.low,
obj.close
]
}
dataPoints.push(newObj);
}
return dataPoints;
}
function updateChart() {
$.ajax({
url: 'http://localhost:8080',
success: function(data) {
candleData = JSON.parse(data);
candleData = mapDataToPointObject(candleData);
chart.render();
}
});
}
$(function(){
setInterval(() => {
updateChart();
}, 500);
});
The data properly loads, parses into the correct format, and render() is called on the interval like it should. The problem is, while the chart axes and titles all render properly, no data shows up. The chart is empty.
What DOES work is setting the data directly to the chart using
chart.options.data[0].dataPoints = candleData;
Why does my above solution not work then? Is there a way I can update the chart's dataPoints without having to hardcode a direct accessor to the chart's dataPoints?
It's related to JavaScript pass by value and pass by reference.
After execution of the following line.
dataPoints: candleData
dataPoints will refer to the current value of candleData. ie. dataPoints = [];
Now if you redefine candleData to any other value.
candleData = JSON.parse(data);
candleData = mapDataToPointObject(candleData);
Then dataPoints won't be aware of this update and will still refer to the empty array (that you pointed earlier).
The following snippet will make it easy to understand
//pass by value
var a = "string1";
var b = a;
a = "string2";
alert("b is: " + b); //this will alert "string1"
//pass by reference
var c = { s: "string1" };
var d = c;
c.s = "string2";
alert("d.s is: " + d.s); //this will alert "string2"
For more, you can read about pass by value and pass by reference.
Javascript by reference vs. by value
Explaining Value vs. Reference in Javascript

Live update highcharts-gauge from dweet

I would like to have the gauge chart update live dweet data, which is success.
The problem is that every time a new data is pushed to the array humidityData, a new pointer is added in the gauge chart as shown here:
guage chart Though I'd like to have one live-updating-pointer instead.
Could this be done by pop() the prev data?
<script language="JavaScript">
//Array to store sensor data
var humidityData = []
<!--START-->
$(document).ready(function() {
//My Dweet thing's name
var name = 'dweetThingName'
//Humidity chart
var setupSecondChart = function() {
var chart2 = {
type: 'gauge'
};
var title = {...};
var pane = {...};
var yAxis = {...};
var tooltip = {
formatter: function () {
return '<b>' + "Humidity: " + Highcharts.numberFormat(this.y, 2) + "%";
}
};
//Series_Humidity
humiditySeries = [{
name: 'Humidity %',
data: humidityData,
tooltip: {
valueSuffix: '%'
}
}]
//Json_Humidity
var humJson = {};
humJson.chart = chart2;
humJson.title = title;
humJson.tooltip = tooltip;
humJson.xAxis = xAxis;
humJson.yAxis = yAxis;
humJson.legend = legend;
humJson.exporting = exporting;
humJson.series = humiditySeries;
humJson.plotOptions = plotOptions;
console.log("Sereies: : " +humJson)
//Container_Humidity
$('#containerHumidity').highcharts(humJson);
}
var humiditySeries = [] ....
dweetio.get_all_dweets_for(name, function(err, dweets){
for(theDweet in dweets.reverse())
{
var dweet = dweets[theDweet];
//Dweet's variables' names
val2 = dweet.content["Humidity"]
//Add the vals into created arrayDatas
humidityData.push(val2)
console.log("HumidityData: " + humidityData)
}
//Call other charts
setupSecondChart()
});
When you initialize/update your chart make sure that data array contains only one element. The dial is created for every point in this array (to visualize it on the plot).

Zingchart last element keeps changing color and not matching with legend

My zingchart's last element's color does not match with legend, and keeps on changing unlike the others. Any Ideas? Everything else works good. Though I'm parsing this data through MySQL database, this is how the JavaScript looks like.
My code:
<script>
var myData = ["12","15","7","20","2","22","10","7","7","10","8","15","9"];
var myData = myData.map(parseFloat);
var myLabels = ["General Verbal Insults","General Beatings\/Pushing","Terrorizing\/Threatening Remarks","False Gossip Inflation (Rumors)","Discrimination","Rough Fighting","Sexual Utterance\/Assaults","General Exclusion","Theft","Racist Utterance\/Assaults","Personal Property Damage","Internet Related (Cyber)","Other\/Unspecified"];
window.onload=function(){
var colorCharacters = "ACDEF0123456789";
var globalStylesArray = [];
var myConfig = {
type: "bar",
legend:{},
title: {
"text":"Showing Results For: Canada",
"color":"green"
},
subtitle: {
"text":"Total Bullying Incidents In Country: 144",
"color":"blue"
},
series : [{"values":[ myData[0] ],"text":"General Verbal Insults",},{"values":[ myData[1] ],"text":"General Beatings/Pushing",},{"values":[ myData[2] ],"text":"Terrorizing/Threatening Remarks",},{"values":[ myData[3] ],"text":"False Gossip Inflation (Rumors)",},{"values":[ myData[4] ],"text":"Discrimination",},{"values":[ myData[5] ],"text":"Rough Fighting",},{"values":[ myData[6] ],"text":"Sexual Utterance/Assaults",},{"values":[ myData[7] ],"text":"General Exclusion",},{"values":[ myData[8] ],"text":"Theft",},{"values":[ myData[9] ],"text":"Racist Utterance/Assaults",},{"values":[ myData[10] ],"text":"Personal Property Damage",},{"values":[ myData[11] ],"text":"Internet Related (Cyber)",},{"values":[ myData[12] ],"text":"Other/Unspecified",}]
};
zingchart.render({
id : 'myChart',
data : myConfig,
width:"100%",
height:500,
});
zingchart.gload = function(p) {
console.log(p);
var graphId = p.id;
var graphData = {};
graphData = zingchart.exec(graphId, 'getdata');
graphData = graphData.graphset[0] ? graphData.graphset[0] : graphData;
console.log(graphData);
createColors(graphData.series[0].values.length);
zingchart.exec(graphId, 'modifyplot', {
data: {
styles: globalStylesArray
}
});
}
function createColors(seriesLength) {
console.log('-------createColor seriesLength: ', seriesLength);
globalStylesArray = [];
for (var i = 0; i < seriesLength; i++) {
var colorString = '#';
for (var j = 0; j < 6; j++) {
colorString += colorCharacters.charAt(Math.floor(Math.random() * (colorCharacters.length - 4)));
}
globalStylesArray.push(colorString);
}
console.log('-----globalStylesArray-------', globalStylesArray);
}
};
</script>
Referring to the comment on the OP:
I just want all color to be different, since i dont know how many elements are in MyData - its generated through PHP & MYSQL
If you just want all of the colors to be different, remove the zingchart.gload function and the createColors function. ZingChart will create different colors for each series dynamically.
If you do want to specify each of those colors ahead of time since you do not know how many series your data will produce, you will need to apply a theme to your chart configuration: http://www.zingchart.com/docs/design-and-styling/javascript-chart-themes/

setting google chart multiple axes from dynamically generated data

I'm trying to replicate the following code from a working example:
series: {0: {targetAxisIndex:0},
1: {targetAxisIndex:0},
2: {targetAxisIndex:1},
This is for setting which y-axis is used to plot different columns from a dataTable on a Google chart.
However I have a variable number of columns (based on user input), therefore am collecting an array of the required axis (the axisAssignment Array in the below example).
My code is below:
var series = {};
for (i=0;i<axisAssignment.length;i++)
{
series[i] = {targetAxisIndex: axisAssignment[i]};
}
return series;
However, all of my data is only being written to the left axis, despite the debugger suggesting that the object is correct. My option code is below:
var options =
{
hAxis: {title: xTitle},
vAxes: {0: {title: y1Type},
1: {title: y2Type}
},
series: calculateSeries(),
pointSize: 1,
legend: {position: 'top', textStyle: {fontSize: 10}}
};
Any assistance would be greatly apreciated.
Thanks
Tom
edit: whole file for reference (it's a work in progress so a bit of a mess I'm afraid)
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawChart());
function drawChart()
{
var title = "Node: "+currentNode;
var xTitle = "Date";
var yTitle = titles[currentVariable];
if (totalData !== null)
{
var tempData = newData();
var tempData2 = totalData;
dataArray[dataCount] = tempData;
var joinMark = countArray(dataCount);
totalData = google.visualization.data.join(tempData2,tempData,'full',[[0,0]],joinMark,[1]);
dataCount = dataCount+1;
}
else
{
totalData = newData();
dataArray[dataCount] = totalData;
dataCount = 1;
}
var options =
{
hAxis: {title: xTitle},
vAxes: {0: {title: y1Type},
1: {title: y2Type}
},
series: calculateSeries(),
pointSize: 0.5,
legend: {position: 'top', textStyle: {fontSize: 10}}
};
var chart = new google.visualization.ScatterChart(document.getElementById('graph'));
console.log(calculateSeries());
chart.draw(totalData, options);
function countArray(count)
{
var arrayCount= new Array();
if (count===1)
{
arrayCount[0] = count;
}
else
{
for (var i=0;i<count;i++)
{
var temp = i+1;
arrayCount[i] = temp;
}
}
return arrayCount;
}
function calculateSeries()
{
var series = {};
for (i=0;i<axisAssignment.length;i++)
{
series[i] = {targetAxisIndex: axisAssignment[i]};
}
return series;
}
function newData()
{
var dataType = dataIn[0];
dataIn.shift();
var axis = dataSelect(dataType);
axisAssignment.push(axis);
var data = new google.visualization.DataTable();
data.addColumn('date', 'Date');
data.addColumn('number', "Node: "+currentNode+": "+titles[currentVariable]);
var num = (dataIn.length);
data.addRows(num/2);
var i = 0;
var j = 0;
while (i<num)
{
var d = (dataIn[i]);
if (i%2===0)
{
d = new Date(d);
data.setCell(j,0,d);
i++;
}
else
{
data.setCell(j,1,parseFloat(d));
i++;
j++;
}
}
return data;
}
function dataSelect(type)
{
var axisNumber;
if (y1Type === null || y1Type === type)
{
y1Type = type;
axisNumber = 0;
}
else if (y2Type === null || y2Type === type)
{
y2Type = type;
axisNumber = 1;
}
else
{
alert("You already have 2 axes assigned.\n\nPlease clear the graph \nor select more objects of \ntype"+y1Type+" or \ntype "+y2Type+" to continue.");
axisNumber = null;
}
return axisNumber;
}
}
Ok, it seems that it's an issue with my choice of ScatterChart,
var options =
{
hAxis: {title: xTitle},
series: calculateSeries(),
vAxes: {0: {title: y1Type },
1: {title: y2Type}
},
pointSize: 0.5,
legend: {position: 'top', textStyle: {fontSize: 10}}
};
var chart = new google.visualization.LineChart(document.getElementById('graph'));
chart.draw(totalData, options);
I've changed it to LineChart and it's working fine, by keeping the pointSize option, the appearance is almost completely unchanged. Thanks for your help juvian.

Add another series to existing plot with flot

I need to know how I can easily add another series to an existing plot using Flot.
Here is how I currently plot a single series:
function sendQuery() {
var host_name = $('#hostNameInput').val();
var objectName = $('#objectNameSelect option:selected').text();
var instanceName = $('#instanceNameSelect option:selected').text();
var counterName = $('#counterNameSelect option:selected').text();
$.ajax({
beforeSend: function () {
$('#loading').show();
},
type: "GET",
url: "http://okcmondev102/cgi-bin/itor_PerfQuery.pl?machine=" + host_name + "&objectName=" + objectName + "&instanceName=" + instanceName + "&counterName=" + counterName,
dataType: "XML",
success: function (xml) {
var results = new Array();
var counter = 0;
var $xml = $.xmlDOM(xml);
$xml.find('DATA').each(function () {
results[counter] = new Array(2);
results[counter][0] = $(this).find('TIMESTAMP').text();
results[counter][1] = $(this).find('VALUE').text();
counter++;
});
plot = $.plot($("#resultsArea"), [{
data: results,
label: host_name
}], {
series: {
lines: {
show: true
}
},
xaxis: {
mode: "time",
timeformat: "%m/%d/%y %h:%S%P"
},
colors: ["#000099"],
crosshair: {
mode: "x"
},
grid: {
hoverable: true,
clickable: true
}
});
You can just add another results set:
// build two data sets
var dataset1 = new Array();
var dataset2 = new Array();
var $xml = $.xmlDOM(xml);
$xml.find('DATA').each(function(){
// use the time stamp for the x axis of both data sets
dataset1[counter][0] = $(this).find('TIMESTAMP').text();
dataset2[counter][0] = $(this).find('TIMESTAMP').text();
// use the different data values for the y axis
dataset1[counter][1] = $(this).find('VALUE1').text();
dataset2[counter][2] = $(this).find('VALUE2').text();
counter++;
});
// build the result array and push the two data sets in it
var results = new Array();
results.push({label: "label1", data: dataset1});
results.push({label: "label2", data: dataset2});
// display the results as before
plot = $.plot($("#resultsArea"), results, {
// your display options
});
At a high-level, the result of your call into itor_PerfQuery.pl will need to be extended to include the additional series data. You'll then want to make your "results" variable a multi-dimensional array to support the additional data and you'll need to update the current xml "find" loop which populates results accordingly. The remainder of the code should stay the same as flot should be able to plot the extended dataset. I think a review of the flot example will help you out. Best of luck.

Categories