How to render jquery jqplot 3 year stacked line graph with a date axis render - jqplot

I would like to be able to use jqplot to stack 3 different years of data on top of each other to compare the data accordingly. The only way to do it that I have found is to "hack" the dates of each result series to use the same year as a base date.
This is not exactly ideal and was wondering if anyone had found a better fix?

I am using C# and javascript to do this for 2 years of data.
In C#
I perform 2 queries to the database getting year1 data and year2 data.
I loop through year2 data setting the year to be the same as year1
I push this data to the client in two arrays. If there is no data for one of the years I set the array to null. Sending an empty array makes jqplot display an empty graph.
I push the two labels for example 2011 and 2010.
On the client
I create an array of data.
If the year array is not null I push it to the array.
I display the charts. I thought I might need to create an array for holding the labels, but jqplot doesn't display the labels when there is no corresponding chart. If you are doing it for three years you will need to have a seperate array for labels.
Here is my C# code:
protected void btnShowGraph_Click(object sender, EventArgs e)
{
SomeRatingSummary SearchCriteria = GetSearchCriteria();
var year1Results = SearchCriteria.ExecuteFind();
string year1Label = SearchCriteria.YearTypeCode;
StringBuilder year1 = getJavaScriptArrayFromRatingsData(year1Results);
int year1int = int.Parse(year1Label);
SearchCriteria.YearTypeCode = (year1int - 1).ToString();
var year2Results = SearchCriteria.ExecuteFind();
year2Results.ToList().ForEach(a => a.FirstSeasonRating = DateTime.Parse(a.FirstSeasonRating).AddYears(1).ToShortDateString());
var year2Label = SearchCriteria.YearTypeCode;
StringBuilder year2 = getJavaScriptArrayFromRatingsData(year2Results);
string script = " jQuery(document).ready(function () {{drawChart('{0}','{1}',{2},{3});}});";
string filledScript = String.Format(script, year1Label, year2Label, year1, year2);
this.Page.ClientScript.RegisterStartupScript(this.GetType(), "callChart", filledScript, true);
}
private static StringBuilder getJavaScriptArrayFromRatingsData(SubSonicList<SomeRatingSummary> results)
{
var firstYear = results.OrderBy(srs => srs.FirstSeasonRating).GroupBy(a => a.FirstSeasonRating).Select(g => new { value = g.Key, count = g.Count() });
string prefix = "[";
StringBuilder year1 = new StringBuilder(prefix);
firstYear.ToList().ForEach(a => year1.AppendFormat("['{0}', {1}],", a.value, a.count));
if (year1.Length > prefix.Length)
{
year1.Length = year1.Length - 1;
year1.Append("]");
}
else
{
year1.Length = 0;
year1.Append("null");
}
return year1;
}
Here is my JavaScript code:
function drawChart(year1Label, year2Label, year1Data, year2Data) {
//these are two sample charts.
//var line1 = [['2008-09-30 4:00PM', 1], ['2008-8-30 4:00PM', 3], ['2008-11-30 4:00PM', 5], ['2008-12-30 4:00PM', 7], ['2009-01-30 4:00PM', 9]];
//var line2 = [['2008-09-31 4:00PM', 5], ['2008-10-20 4:00PM', 2], ['2008-11-15 4:00PM', 4], ['2008-12-16 4:00PM', 9], ['2009-01-29 4:00PM', 8]];
var chartData = [year1Data];
if (year2Data != null) {
chartData.push(year2Data);
}
var plot1 = jQuery.jqplot('chart1', chartData, {
grid: {
//background:'#f0ffff',
background: '#F0F8FF',
gridLineColor: '#dfdfdf',
borderWidth: 1.5
},
title: 'Ratings by Day',
axes: { xaxis: {
renderer: jQuery.jqplot.DateAxisRenderer,
rendererOptions: { tickRenderer: jQuery.jqplot.CanvasAxisTickRenderer },
tickInterval: '2 month',
tickOptions: { formatString: '%b' }
}
},
legend: { show: true, location: 'e', showSwatch: true },
seriesDefaults: { showMarker: false, lineWidth: 1.5, markerOptions: { style: 'square'} },
series: [{ label: year1Label }, { label: year2Label}]
});
};

Related

multi-line chart animation code modify google charts

I found the code from here:
On load Google LineChart animation
google.load('visualization', '1', { packages: ['corechart'], callback: function() {
var data = new google.visualization.DataTable();
data.addRows(5);
data.addColumn('string', '');
data.addColumn('number', 'Sales');
data.addRows(5);
data.setValue(0, 0, 'Jan');
data.setValue(1, 0, 'Feb');
data.setValue(2, 0, 'Mar');
data.setValue(3, 0, 'Apr');
data.setValue(4, 0, 'May');
var options = {
title: 'Sales by months for 2013 year', curveType: 'function',
"vAxis": { "minValue": "0", "maxValue": 6 }, "hAxis": { "slantedTextAngle": "45", "slantedText": "true" }, "legend": { "position": "top" }, "pointSize": "5",
animation: { duration: 250 }
};
var chart = new google.visualization.LineChart(document.getElementById('test'));
var index = 0;
var chartData = [ 5, 1, 4, 2, 3 ]
var drawChart = function() {
console.log('drawChart index ' + index);
if (index < chartData.length) {
data.setValue(index, 1, chartData[index++]);
chart.draw(data, options);
}
}
google.visualization.events.addListener(chart, 'animationfinish', drawChart);
chart.draw(data, options);
drawChart();
}});
If I want to create multi-line, how to modify this code? Thanks!
I'm not a javascript programmer and not familiar with OOP
The author is OneMoreVladimir, but I don't have the access to comment under his post.
google.load('visualization', '1', {
packages: ['corechart'],
callback: function() {
var data = new google.visualization.DataTable();
data.addRows(5);
data.addColumn('string', '');
data.addColumn('number', 'Sales');
data.addColumn('number', 'Sales2');
data.addRows(5);
data.setValue(0, 0, 'Jan');
data.setValue(1, 0, 'Feb');
data.setValue(2, 0, 'Mar');
data.setValue(3, 0, 'Apr');
data.setValue(4, 0, 'May');
var options = {
title: 'Sales by months for 2013 year',
curveType: 'function',
"vAxis": {
"minValue": "0",
"maxValue": 8
},
"hAxis": {
"slantedTextAngle": "45",
"slantedText": "true"
},
"legend": {
"position": "top"
},
"pointSize": "5",
animation: {
duration: 600
}
};
var chart = new google.visualization.LineChart(document.getElementById('test'));
var index = 0;
var chartData = [5, 1, 4, 2, 3]
var drawChart = function() {
console.log('drawChart index ' + index);
if (index < chartData.length) {
data.setValue(index, 1, chartData[index++]);
chart.draw(data, options);
}
}
var index1 = 0;
var chartData1 = [1, 3, 4, 6, 5]
var drawChart1 = function() {
console.log('drawChart1 index1 ' + index1);
if (index1 < chartData1.length) {
data.setValue(index1, 2, chartData1[index1++]);
chart.draw(data, options);
}
}
google.visualization.events.addListener(chart, 'animationfinish', drawChart);
google.visualization.events.addListener(chart, 'animationfinish', drawChart1);
chart.draw(data, options);
drawChart();
drawChart1();
}
});
I figure out! Here is the code.
But another question, the code pass the http://jsfiddle.net and run very well, but when I copy paste it into the HTML why it doesn't work? Did I miss something?

How to draw line plus bar chart using highcharts/d3.js or any other chart library?

How to draw line plus bar chart as below using highcharts/d3.js or any other chart library?
So What exactly I am trying to achieve is "Display bar if no data available for particular time interval" (here chart says that there is not data available for time interval (17:30-18:30)).
Also you can use Highcharts with plotBands functionality (which should be more elastic). There is the algorithm implemented on chart.events.load which checks whether the nulls are in data, and adds the plot bands to your chart dynamically basing on your current data. Take a look at this code:
load() {
var axis = this.xAxis[0]
var boundaries = []
var color = '#55f'
// Check there are nulls in data. If yes, save the boundaries.
data.forEach((elem, i) => {
if (elem === null) {
if (data[i-1]) { boundaries.push(data[i-1][0]) }
if (data[i+1]) { boundaries.push(data[i+1][0]) }
}
})
// Create plotBands basing on current boundaries.
boundaries.forEach((range, i) => {
if (i % 2) {
axis.addPlotBand({
from: boundaries[i-1],
to: range,
color: color
})
}
})
}
Additionally, you can add another series to your chart (fake one, with empty data), which will serve to toggling visibility of plot bands. Here is the code:
{
// Fake series to add toggling visibility of plotbands functionality.
name: "Zone of Unavailability",
data: [],
events: {
legendItemClick() {
var bandsGroup = this.chart.xAxis[0].plotLinesAndBandsGroups['bands-0']
var bandsVisibility = bandsGroup.attr('opacity')
bandsGroup.attr({
opacity: bandsVisibility ? 0 : 1
})
}
}
}
Live example: http://jsfiddle.net/dzj8bwLm/
API Reference:
https://api.highcharts.com/highcharts/xAxis.plotBands
https://api.highcharts.com/highcharts/series.line.events.legendItemClick
You can use Highcharts/Highstock for this. You can put line and column series into one chart and manipulate them however you like.
<script src="https://code.highcharts.com/stock/highstock.js"></script>
<div id="container" style="height: 400px; min-width: 600px"></div>
and
var data = [];
for (let i = 0; i < 100; i++) {
if (i == 10 || i == 11 || i == 12 || i == 13 || i == 14 || i == 15 || i == 16 || i == 17 || i == 18 || i == 27 || i == 28 || i == 29) {
data.push(null)
} else {
data.push([i, Math.floor((Math.random() * 100) + 1)])
}
}
Highcharts.stockChart('container', {
xAxis: {
ordinal: false,
labels: {
format: '{value}'
}
},
series: [{
data: data,
connectNulls: false,
dataGrouping: {
enabled: false
}
}, {
type: 'column',
pointWidth: 9,
dataGrouping: {
enabled: false
},
data: [
[10, 100],
[11, 100],
[12, 100],
[13, 100],
[14, 100],
[15, 100],
[16, 100],
[17, 100],
[18, 100],
[27, 100],
[28, 100],
[29, 100]
]
}]
});
See this online demo: jsFiddle

Handsontable cross calculations

I have a handontable demo.
document.addEventListener("DOMContentLoaded", function() {
var
example = document.getElementById('example1'),
hot1;
hot1 = new Handsontable(example, {
data: [
['', '', '', ''],
[1, 2, 3, '=SUM(A2:C2)'],
[1, 2, 3],
],
width: 584,
height: 320,
rowHeaders: true,
formulas: true,
colHeaders: true,
columns: [1, 2, 3, 4],
columnSummary: function () {
var summary = [];
for (var i = 0; i < 4; i++) {
summary.push({
ranges: [[1, 2]],
destinationRow: 0,
destinationColumn: i,
type: 'sum',
forceNumeric: true,
sourceColumn: i
});
}
return summary;
}
});
});
It caclulates:
Sum of column and puts a result in the first raw.
Sum of rows (except first one) and puts it in the column "D"
I need to calculate correct total of the totals, which is the cell D1.
After loading and changing any cell calculation of D1 has to work properly.
Thank you for any ideas.
The option columnSummary should not be applied on the 4th column (the column of SUM results). Try to apply you code of columnSummary option only for the first three columns :
for (var i = 0; i < 3; i++) //Instead of i < 4
And use in the row one what you use to calculate the sum on your other rows :
data: [
['', '', '', '=SUM(A1:C1)'],
[1, 2, 3, '=SUM(A2:C2)'],
[1, 2, 3, '=SUM(A3:C3)'],
],
You will see that it works like a charm : JSFiddle.

Highcharts - draw line chart with summed values but show breakup on hover

I am using Highcharts - Line - Ajax.
Let's say I have two series of data - 'Headcount 1' and 'Headcount 2'. I want to draw a line graph of 'Headcount', which is the sum of the 2 series. However, when someone hovers on one data point, I want to show the individual values in the callout. Is this possible? How can I do this?
e.g.
H1 = (1, 2, 3)
H2 = (5, 6, 7)
Ht = (6, 8, 10)
I will draw a line graph with Ht. If I hover on '6' on the chart, the callout should show the values of H1 = 1 and H2 = 5
You can set the visibility for series H1 and H2 to false,
series: [{
name: 'H1',
data: [1, 2, 3],
visible: false,
showInLegend: false
}, {
name: 'H2',
data: [5, 6, 7],
visible: false,
showInLegend: false
}, {
name: 'H',
data: [6, 8, 10]
}]
and edit tooltip formatter to display what you want
tooltip: {
formatter: function() {
var s = '<b>' + this.x + '</b>';
var chart = this.points[0].series.chart; //get the chart object
var categories = chart.xAxis[0].categories; //get the categories array
var index = 0;
while(this.x !== categories[index]){index++;} //compute the index of corr y value in each data arrays
$.each(chart.series, function(i, series) { //loop through series array
if (series.name !== 'H') {
s += '<br/>'+ series.name +': ' +
series.data[index].y +'m'; //use index to get the y value
}
});
return s;
},
shared: true
}
Have a look at jsfiddle.net/s190ebby/27/
Yes
Points can have custom property, taking care that the names do not shadow highcharts variable names.
var data = [{
y: 6,
h1Value: 1,
h2Value: 5
},{
y: 8,
h1Value: 2,
h2Value: 6
}];
Set your series to this data in your config object, by series: data
Customise the tooltip as:
tooltip: {
pointFormat: '<b>H Value</b>: {point.y}<br/>
<b>H1 Value</b>: {point.h1Value}<br/>
<b>H2 Value</b>: {point.h2Value}'
}

DOJO onclick on a pie chart slice for drill down

I tried to find several places how this work but could not.
The requirement is to drill down by clicking on the slice of the pie to next level. I can get the onclick even but not sure how to get the value from the chart. Everywhere it is pointing to http://www.sitepen.com/blog/2008/05/27/dojo-charting-event-support-has-landed/ but nowhere any live demo is given. Till now i have managed to get the onclick.
chart.addSeries("Monthly Sales - 2010", chartData);
var h = chart.connectToPlot("default", function(o){
if(o.type == "onclick"){
alert("clicked!");
}
});
var store = new dojo.store.Memory({data: [
{ id: '2', value: 10, usedForDrillDown:'x' },
{ id: '3', value: 5, usedForDrillDown: 'y' },
{ id: '4', value: 8, usedForDrillDown:'z' }
]});
// adapter needed, because the chart uses the dojo.data API
var storeAdapter = new dojo.data.ObjectStore({
objectStore: store
});
var ds = new dojox.charting.DataSeries(
storeAdapter/*, { query: { needed if the store contains more than data points } }*/);
var chart = new dojox.charting.Chart("chart");
chart.addPlot("default", { type: "Pie" });
chart.addSeries("default", ds);
chart.connectToPlot("default", function(evt) {
if(evt.type == "onclick"){
var itm = evt.run.source.items[evt.index];
console.dir(itm);
}
});
chart.render();

Resources