Creating dynamic labels for dojo bar chart - dojo

I have bar chart, whose x-axis labels is generated dynamically from db, I am getting these values through ajax call data
'{value:1,text:"x"},{value:2,text:"Vikash"},{value:3,text:"y"},{value:4,text:"z"}'.
How to pass these values to label parameter. I tried passing it as an array and also as json but nothing seems to work.. Any ideas..
Here is my code:
makeBarChart=function() {
animChart = new dojox.charting.Chart2D("animChart");
animChart.setTheme(dojox.charting.themes.MiamiNice)
.addAxis("x",{
labels: [ myLabelSeriesarray ], gap: 20}).
addAxis("y", {
vertical: true,
fixLower: "major",
fixUpper: "major",
includeZero: true
}).
addPlot("default", {
type: "ClusteredColumns",
gap: 10
}).
addSeries("Series A", closedSeries).
addSeries("Series B", othersSeries).
render();
};
dojo.addOnLoad(makeBarChart);

jsp code:
var labelDis = new Array(pieData.length); // pieData is the JSON value getting from Java
for(var i = 0;i<pieData.length;i++){
labelDis[i] = new Array(2);
labelDis[i]['value'] = i + 1;
labelDis[i]['text'] = pieData[i]['axis'];
}
Java/Servlet code:
JSONObject jSONObject = new JSONObject();
jSONObject.put("axis", "value from database");
jSONArray.put(jSONObject);
out.print(jSONArray.toString());

Suppose you have received data in json format through ajax call and you want to create dynamic labels using that data.
var jsonArray= ["label1","label2","label3"];
var labelsArray = [];
for (var i = 0; i < jsonArray.length; i++,) {
var obj = {};
obj.value = i;
obj.text = jsonArray[i];
labelsArray.push(obj);
}
Set the labels in x Axis to this labelsArray
this.chart1.addAxis("x", {
title: "Collection Date",
titleOrientation: "away",
titleGap:20,
labels:labelsArray
})

Related

c3.js total count in title of pie chart

I have a question about the pie chart in c3.js.
How can I add the total count of a pie chart in the title??
var title = new Array('data1.sql','data2.sql')
var dtitle = new Array('title1','title2')
var chart = new Array('chart0', 'chart1')
for(var i = 0; i < title.length; i++){
chart[i] = c3.generate({
bindto : '#chart' + i,
size: {
height: 550,
width: 800
},
data : {
url : '/json/sql/data/test/' + title[i],
mimeType : 'json',
type : 'donut'
},
donut: {
title: dtitle[i] + ' - Total:' ,
label: {
format: function(value, ratio, id) {
return value;
}
}
}
});
}
The annoying thing here is that the title option can take a function, but the chart variable is not initialised within it so using the c3 api methods can't be done at this point.
So the best (maybe only) way is to add an onrendered callback that adds up the data as you'd need to anyways and then replace the text in the chart's title text using a spot of d3:
onrendered: function () {
var data = this.api.data();
var total = data.reduce (function (subtotal, t) {
return subtotal + t.values.reduce (function (subsubtotal,b) { return subsubtotal + b.value; }, 0);
}, 0);
d3.select(this.config.bindto + " .c3-chart-arcs-title").text("Total: "+total);
}
Edit: If you want it to keep track of a total as you hide/show series use this
var data = this.api.data.shown.call (this.api);
instead of
var data = this.api.data();

Pivot data dynamically for google line chart

I want to display "population" of various countries through the years in the same line chart. The data displayed is based on selections from a multi-select dropdown "Countries". Underlying Data Table has 3 columns:
Year, Country, Population
2012,countryA,33
2013,countryA,35
2014,countryA,40
2012,countryB,65
2013,countryB,70
2014,countryB,75
2012,countryC,15
2013,countryC,20
2014,countryC,25
I am trying to create a pivoted Data View from the underlying Data Table
The code I am using is:
function drawLineChart() {
var arr = $('#country').val();
var lineChartJson = $.ajax({
url: "../json/lineChart.json",
dataType: "json",
async: false
}).responseText;
var lineChartData = new google.visualization.DataTable(lineChartJson);
var view = new google.visualization.DataView(lineChartData);
var viewCols = [0];
for(var i = 0; i < arr.length; i++) {
var viewCols1 = [{
type: 'number',
label: arr[i],
calc: function (dt, row) {
return (dt.getValue(row, 1) == arr[i]) ? dt.getValue(row, 2) : null;
}
}];
viewCols = viewCols.concat(viewCols1);
}
view.setColumns(viewCols);
var aggCols = [{
column: 1,
type: 'number',
label: view.getColumnLabel(1),
aggregation: google.visualization.data.sum
}];
for(var i = 2; i < 4; i++) {
var aggCols1 = [{
column: i,
type: 'number',
label: view.getColumnLabel(i),
aggregation: google.visualization.data.sum
}];
aggCols = aggCols.concat(aggCols1);
}
var pivotedData = google.visualization.data.group(view, [0], aggCols);
But this does not seem to work as expected and I just get 1 Line in the chart with values for all countries added up (although I can see the legend for 3 countries)
On the other hand if I set my View columns as below, it works as expected.
view.setColumns([0, {
type: 'number',
label: arr[0],
calc: function (dt, row) {
return (dt.getValue(row, 1) == arr[0]) ? dt.getValue(row, 2) : null;
}
}, {
type: 'number',
label: arr[1],
calc: function (dt, row) {
// return values of C only for the rows where B = "bar"
return (dt.getValue(row, 1) == arr[1]) ? dt.getValue(row, 2) : null;
}
}, {
type: 'number',
label: arr[2],
calc: function (dt, row) {
return (dt.getValue(row, 1) == arr[2]) ? dt.getValue(row, 2) : null;
}
}]);
What is going wrong in the loop? Is something wrong with "concat" in the loop where I am creating View Columns? I also saw the viewCols array by using console.log and it seems to have the right elements
I was trying to follow the below post:
Creating pivoted DataView from existing google charts DataTable object
the problem has to do with scope
arr[i] is undefined within calc: function (dt, row)
here is another way to pivot the data...
google.charts.load('current', {
callback: function () {
var arr = [
'countryA',
'countryB',
'countryC'
];
var lineChartData = google.visualization.arrayToDataTable([
['Year', 'Country', 'Population'],
[2012,'countryA',33],
[2013,'countryA',35],
[2014,'countryA',40],
[2012,'countryB',65],
[2013,'countryB',70],
[2014,'countryB',75],
[2012,'countryC',15],
[2013,'countryC',20],
[2014,'countryC',25]
]);
// sort by year
lineChartData.sort([{column: 0}]);
// get unique countries
var countryGroup = google.visualization.data.group(
lineChartData,
[1]
);
// build country data table
var countryData = new google.visualization.DataTable({
cols: [
{label: 'Year', type: 'number'},
]
});
// add column for each country
for (var i = 0; i < countryGroup.getNumberOfRows(); i++) {
countryData.addColumn(
{label: countryGroup.getValue(i, 0), type: 'number'}
);
}
// add row for each year / country
var rowYear;
var rowIndex;
for (var i = 0; i < lineChartData.getNumberOfRows(); i++) {
if (rowYear !== lineChartData.getValue(i, 0)) {
rowYear = lineChartData.getValue(i, 0);
rowIndex = countryData.addRow();
countryData.setValue(rowIndex, 0, rowYear);
}
for (var x = 1; x < countryData.getNumberOfColumns(); x++) {
if (countryData.getColumnLabel(x) === lineChartData.getValue(i, 1)) {
countryData.setValue(rowIndex, x, lineChartData.getValue(i, 2));
}
}
}
// draw agg table
new google.visualization.ChartWrapper({
chartType: 'Table',
containerId: 'table-div',
dataTable: countryData
}).draw();
// draw line chart
new google.visualization.ChartWrapper({
chartType: 'LineChart',
containerId: 'chart-div',
dataTable: countryData
}).draw();
},
packages: ['corechart', 'table']
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="table-div"></div>
<div id="chart-div"></div>
I could figure out the problem with my code above.
"calc" is the callback function in loop. So only last value of loop variable "i" is visible within the loop.
Putting a wrapper function fixes it:
for(var i = 0; i <= arr.length; i++)(function(i) {
var viewCols1 = [{
type: 'number',
label: arr[i],
calc: function (dt, row) {
return (dt.getValue(row, 1) == arr[i]) ? dt.getValue(row, 2) : null;
}
}];
viewCols = viewCols.concat(viewCols1);
})(i);

jqGrid ASP.NET MVC4 initial sort

I'm using jqGrid as TreeGrid with ASP.NET MVC4 and have one problem:
My Model:
OrdersGrid = new JQGrid
{
Columns = new List<JQGridColumn>()
{
new JQGridColumn
{
DataField = "MeasureId",
// always set PrimaryKey for Add,Edit,Delete operations
// if not set, the first column will be assumed as primary key
PrimaryKey = true,
Visible = false,
Sortable = false
},
new JQGridColumn
{
DataField = "Name",
Width = 100,
Sortable = true
},
new JQGridColumn
{
DataField = "Symbol",
Width = 100
},
},
Width = Unit.Pixel(640),
Height = Unit.Percentage(100),
TreeGridSettings = new TreeGridSettings
{
Enabled = true
},
SortSettings = new SortSettings
{
AutoSortByPrimaryKey = false,
InitialSortColumn = "Name",
InitialSortDirection = SortDirection.Asc
}
};
My Controller:
public JsonResult DataRequested()
{
// Get both the grid Model and the data Model
// The data model in our case is an autogenerated linq2sql database based on Northwind.
var gridModel = new NavigatorModel();
...
var hierarchyRows = from measure in measures
select new
{
MeasureId = measure.MeasureId,
Name = measure.Name,
Symbol = measure.Symbol,
//ParentID = measure.ParentMeasureId != null ? measure.ParentMeasureId.ToString() : "",
tree_loaded = true,
tree_parent = measure.ParentMeasureId,
tree_level =LoadAllRowsExpanded_GetRowLevel(measure.ParentMeasureId, measures),
tree_leaf = LoadAllRowsExpanded_IsLeafRow(measure.MeasureId, measures),
tree_expanded = true
};
//var dataModel = new
// return the result of the DataBind method, passing the datasource as a parameter
// jqGrid for ASP.NET MVC automatically takes care of paging, sorting, filtering/searching, etc
return gridModel.OrdersGrid.DataBind(hierarchyRows.AsQueryable());
}
As above you can see that I'm setting the AutoSortByPrimaryKey set to false, but when the page is loaded, grid looks like that:
When I click on one of columns (Name or Symbol) to sort everything becomes fine - the Measure which is wrongly displayed goes under it's parent.
I have tried also with event to sort after "gridInitialize" but also no success.
Any ideas?

How to set the initial map area in OpenLayers?

I'm using Patrick Wied's OpenLayers Heatmap layer, but only for locations in the UK.
How can I preset the initial map display area to show just the UK?
Here's the code I've used in an ASPX page
var map, layer, heatmap;
function init() {
var testData = <asp:literal id="cLtMapData" runat="server" />
var transformedTestData = { max: testData.max, data: [] },
data = testData.data,
datalen = data.length,
nudata = [];
// in order to use the OpenLayers Heatmap Layer we have to transform our data into
// { max: <max>, data: [{lonlat: <OpenLayers.LonLat>, count: <count>},...]}
while (datalen--) {
nudata.push({
lonlat: new OpenLayers.LonLat(data[datalen].lon, data[datalen].lat),
count: data[datalen].count
});
}
transformedTestData.data = nudata;
map = new OpenLayers.Map('heatmapArea');
layer = new OpenLayers.Layer.OSM();
// create our heatmap layer
heatmap = new OpenLayers.Layer.Heatmap("Heatmap Layer", map, layer, { visible: true, radius: 10 }, { isBaseLayer: false, opacity: 0.3, projection: new OpenLayers.Projection("EPSG:4326") });
map.addLayers([layer, heatmap]);
map.zoomToMaxExtent();
//maxExtent: new OpenLayers.Bounds(-1*b, -1*b, b, b);
map.zoomIn();
heatmap.setDataSet(transformedTestData);
}
It's almost exactly like Patrick's demo pages, but with one difference - var testData = (an asp literal) - so that I can use dynamic data selected bu the user, and retrieved from an SQL Database via a stored procedure that translates UK postcodes into latitude and longitude.
I would do it in the map initialization. Something like this:
map = new OpenLayers.Map({
projection: new OpenLayers.Projection("EPSG:900913"),
units: "m",
numZoomLevels: 18,
maxResolution: 156543.0339,
maxExtent: new OpenLayers.Bounds(
-20037508.34, -20037508.34, 20037508.34, 20037508.34
),
layers: [
new OpenLayers.Layer.OSM("OpenStreetMap", null, {
transitionEffect: 'resize'
})
],
center: new OpenLayers.LonLat(-10309900, 4215100),
zoom: 4
});
var lat = -3.841867446899414;
var lon = 43.466002139041116;
var zoom = 0;
var fromProjection = new OpenLayers.Projection("EPSG:28992"); // EPSG:4326Transform from WGS 1984
var toProjection = new OpenLayers.Projection("EPSG:900913"); // to Spherical Mercator Projection
var position = new OpenLayers.LonLat(lon, lat).transform(fromProjection, toProjection);
var options = {
controls: [
new OpenLayers.Control.Navigation(),
new OpenLayers.Control.MousePosition(),
new OpenLayers.Control.PanZoomBar(),
new OpenLayers.Control.Permalink()
]
};
map = new OpenLayers.Map("basicMap", options);
var mapnik = new OpenLayers.Layer.OSM();
map.addLayer(mapnik);
map.setCenter(position, zoom);

Adding Columns Dynamically to SlickGrid with AJAX. Columns don't show up

Using SlickGrid to display some pretty elaborate grids. The Example I am showing here isn't my code but basically an example given by the SlickGrid people duplicating my issue. My Grids need to have columns added dynamically with the column names being fed through an AJAX feed. Creating the column object in JS is not a problem and even adding them using the .push is seems to work fine as I can see them in the firebug console. The new columns never seem to rendner. I get a a bunch of tiny empty cells at the end of the grid but they never populate.
The script below can be replaced with the script in the "example1-simple.html" viewed here.
<script src="../lib/jquery.jsonp-1.1.0.min.js"></script>
<script>
var grid;
var data = [];
var columns = [
{id:"title", name:"Title", field:"title"},
{id:"duration", name:"Duration", field:"duration"},
{id:"%", name:"% Complete", field:"percentComplete"},
{id:"start", name:"Start", field:"start"},
{id:"finish", name:"Finish", field:"finish"},
{id:"effort-driven", name:"Effort Driven", field:"effortDriven"}
];
var dynamicColumns = [];
var options = {
enableCellNavigation: true,
enableColumnReorder: false
};
$(function() {
data = [];
BuildExtraColumnsAJAX();
for (var i = 0; i < 2000; i++) {
data[i] = {
title: "Task " + i,
duration: "5 days",
percentComplete: Math.round(Math.random() * 100),
start: "01/01/2009",
finish: "01/05/2009",
effortDriven: (i % 5 == 0)
};
for (var x = 0; x < 20; x++) {
var columnName = "dynamicColumn" + x;
data[i][columnName] = x;
}
}
//alert("Go Pack Go");
grid = new Slick.Grid("#myGrid", data, dynamicColumns, options);
$("#myGrid").show();
})
function BuildExtraColumnsAJAX(){
//dynamicColumns = [];
for (var x = 0; x < columns.length; x++){
dynamicColumns.push(columns[x]);
}
var url = "http://services.digg.com/search/stories? query=apple&callback=C&offset=0&count=20&appkey=http://slickgrid.googlecode.com&type=javascript";
$.jsonp({
url: url,
callbackParameter: "callback",
cache: true, // Digg doesn't accept the autogenerated cachebuster param
success: onSuccess,
error: function(){
alert("BOOM Goes my world");
}
});
}
function onSuccess(resp) {
for (var i = 0; i < resp.stories.length; i++) {
dynamicColumns.push( {
id: "dynamicColumn" + i,
name: "Dynamic Column" + i,
field: "dynamicColumn" + i
});
}
}
function BuildExtraColumns(){
dynamicColumns = [];
for (var x = 0; x < columns.length; x++){
dynamicColumns.push(columns[x]);
}
for (var i = 0; i < 20; i++) {
dynamicColumns.push( {
id: "dynamicColumn" + i,
name: "Dynamic Column" + i,
field: "dynamicColumn" + i
});
}
}
If I put the line grid = new Slick.Grid("#myGrid", data, dynamicColumns, options); in the firebug console and run it the grid than renders fine. It is almost like the script is still executing lines of code even though its not done creating the dynamicColumns.
The Digg AJAX call is just to similute an AJAX call, I of course would be using my own.
The grid is getting initialized before the AJAX call to get the additional columns completes.
Either wait until the columns have loaded to initialize the grid, or update the grid after the additional columns have loaded:
grid.setColumns(dynamicColumns);