Marcus Koz Marcus Koz - 1 month ago 29
Ruby Question

How to implement Highcharts column-drilldown chart in Rails application?

I'm trying to implement a Highcharts Column-Drilldown Chart in my Rails application using lazy_high_charts. I want to display data that's being pulled from my database and stored in four arrays (areas, areaScores, departments, and deptScores). I'm having trouble converting the JS from the example (JSFiddle) listed on the highchart site into ruby. I have not been able to find any resources on creating a column-drilldown chart in ruby. Any help on how to integrate the drilldown chart into my ruby application would be highly appreciated.

I have included the sample JavaScript shown on the Highcharts demo page and my controller method that populates the four arrays with data and builds the highchart.

Highcharts Column-Drilldown Chart Example (Javascript)

$(function () {

Highcharts.data({
csv: document.getElementById('tsv').innerHTML,
itemDelimiter: '\t',
parsed: function (columns) {

var brands = {},
brandsData = [],
versions = {},
drilldownSeries = [];

// Parse percentage strings
columns[1] = $.map(columns[1], function (value) {
if (value.indexOf('%') === value.length - 1) {
value = parseFloat(value);
}
return value;
});

$.each(columns[0], function (i, name) {
var brand,
version;

if (i > 0) {

// Remove special edition notes
name = name.split(' -')[0];

// Split into brand and version
version = name.match(/([0-9]+[\.0-9x]*)/);
if (version) {
version = version[0];
}
brand = name.replace(version, '');

// Create the main data
if (!brands[brand]) {
brands[brand] = columns[1][i];
} else {
brands[brand] += columns[1][i];
}

// Create the version data
if (version !== null) {
if (!versions[brand]) {
versions[brand] = [];
}
versions[brand].push(['v' + version, columns[1][i]]);
}
}

});

$.each(brands, function (name, y) {
brandsData.push({
name: name,
y: y,
drilldown: versions[name] ? name : null
});
});
$.each(versions, function (key, value) {
drilldownSeries.push({
name: key,
id: key,
data: value
});
});

// Create the chart
$('#container').highcharts({
chart: {
type: 'column'
},
title: {
text: 'Browser market shares. November, 2013'
},
subtitle: {
text: 'Click the columns to view versions. Source: netmarketshare.com.'
},
xAxis: {
type: 'category'
},
yAxis: {
title: {
text: 'Total percent market share'
}
},
legend: {
enabled: false
},
plotOptions: {
series: {
borderWidth: 0,
dataLabels: {
enabled: true,
format: '{point.y:.1f}%'
}
}
},

tooltip: {
headerFormat: '<span style="font-size:11px">{series.name}</span><br>',
pointFormat: '<span style="color:{point.color}">{point.name}</span>: <b>{point.y:.2f}%</b> of total<br/>'
},

series: [{
name: 'Brands',
colorByPoint: true,
data: brandsData
}],
drilldown: {
series: drilldownSeries
}
})

}
});
});


My Controller:

def generateOrgBreakdownReport
# First, query the database for the data you need for the report
@jsonanswerBRKD = queryDatabaseForOrgProgressReport()

# Second, process and combine data as needed for the report
@areaBreakdown, @deptBreakdown, @employBreakdown = computeAreaAndDeptPrepareScore(@jsonanswerBRKD)

# Third, you'll need to put the processed data into a format
# Highcharts will understand for the data series it uses
# for the graph.

#THESE ARRAYS HOLD THE NAMES AND SCORES OF AREAS AND DEPARTMENTS
@deptScores, @departments, @areaScores, @areas = cycleThroughProcessedDataAndCreateHighChartsDataSetsBreakdown(@areaBreakdown, @deptBreakdown, @employBreakdown)

# Last, we put the newly made data sets for Highcharts to work its magic.

#DONT KNOW HOW TO IMPLEMENT DRILLDOWN FOR RUBY
@orgBreakdown = LazyHighCharts::HighChart.new('column') do |f|
f.chart( type: 'column' )
f.xAxis(
title: { text: "Areas" },
type: 'category'
)
f.yAxis(
title: { text: "Preparedness Score (%)"},
)
f.series(
name: "Department Score",
colorByPoint: true,
data: @deptScores
)
f.series(
name: "Area Score",
data: @areaScores
)
f.title(
text: "Organizational Breakdown"
)
f.options[:xAxis][:categories] = @areas
f.drilldown({:series=>{
name:"Dept. Score",
data: @deptScore
}
})

end
end


Thanks,
Matt

Answer

I haven't used Lazy Highcharts, but assuming it mirrors the JSON from the JavaScript API you need to add the sub-series by name, e.g.

  f.series(
    name: "Department Score",
    colorByPoint: true, 
    data: @deptScores,
    drilldown: "subdept"  #add this 
  )

Then you'll need to add drilldown data, and if Lazy Highcharts supports it, it might look something like this:

  f.drilldown(
    series: {
      id: "subdept",
      data: [
        ["One", 1],
        ["Two", 2],
        ["Three", 3]
      ]
    }
  )

See this basic drilldown fiddle to see how the resulting Javascript should look.

Comments