Related
I have JSON data source with nested obvar
jsonData = {
"block":[
{"name": "Block 1. Social Work",
"subblock": [{
"name": "Block 1.1. Student Org (SO)",
"paragraph": [
{
"name": "Head of SO",
"score": "10,00"
}, {
"name": "Head of Group" ,
"score": "9, 00 "
}]
}]
}]
};
Wher block.name = table caption, subblock.name =
var subbl_content=document.createElement("th");
subbl_content.colSpan=4;
subbl_content.innerHTML=jsonData[0].block[0].subblock[0].name;
paragraph = table content. I try to place it to DataTable in the following way
$(document).ready(function() {
.....
$('#example').DataTable(
{
data: jsonData,
columns: [
{ data: 'block[0].subblock[0].paragraph[0].name' },
{ data: 'block[0].subblock[0].paragraph[0].score' }
]
});
}) ;
It would seem that must work but as a result i have in one Cell next value Head of SOiHead of Group. But when i some change data like
$('#example').DataTable(
{
data: jsonData.block[0].subblock[0].paragraph,
columns: [
{ data: 'name' },
{ data: 'score' }
]
});
All works. Is it normal or are there other methods of solution?
Here is an example of google column chart built using static data : https://plnkr.co/edit/WBApWlwTIDa7HjOQMyxe?p=preview
I want to draw the chart dynamically.One issue i'm facing is how to dynamically assign the value for ticks:[..]
Please find the updated plunker https://plnkr.co/edit/EGzl2XdQfuMWldzPyfr6?p=preview.
I tried to assign the values for ticks:[..] later by creating a varibale dynamicTicks but it is not working .
PS: Reference tooltip is not shown as expected when customized
--EDITED--
Below is the updated code suggested by #WhiteHat in below thread.
Below is the js code to dynamically get the data and display the chart.Issue is with the below code the h-axis dynamicTrick is not displayed, on h-axis it is showing the values given in f: property of {"v": i, "f": hAxisValue}
app.controller('myController', ['$scope', '$uibModal', 'MyService', function ($scope, $uibModal, MyService) {
$scope.chart = {};
$scope.chart.type = "ColumnChart";
$scope.chart.displayed = false;
var dynamicTicks = [];
$scope.chart.options = {
focusTarget: 'category',
"fill": 20,
"displayExactValues": true,
"isStacked": 'true',
tooltip: {text: 'value',textStyle: {fontName: '"Arial"'}},
hAxis: {
titleTextStyle: {bold: 'true'},
slantedText: false,
ticks: dynamicTicks
},
};
$scope.chart.view = {
columns: [0, 1, 2, 3]
};
$scope.chart.data = {
"cols": [
{id: "label", label: "Label", type: "string"},
{id: "count", label: "Count", type: "number"},
{id: "pizza", label: "Pizza", type: "number"},
{id: "softDrink", label: "SoftDrink", type: "number"},
]
};
$scope.loadMyChart = function () {
MyService.getChartData().then(
function (response) {
$scope.myResponse= response;
//check for error
var count = 0;
var pizza = 0;
var softDrink = 0;
var myRows = [];
$scope.chart.data.rows = {};
var i = 0; var cData=[];
angular.forEach($scope.myResponse, function (value, key) {
count = value.myData.count;
pizza = value.myData.pizza;
softDrink = value.myData.softDrnk;
hAxisValue = value.myData.title;
cData = {
"c": [{"v": i, "f": hAxisValue}, {"v": passsed},
{"v": failed},
{"v": notExecute}, {"v": key}]
};
myRows.push(cData); i++;
});
alert("cData.length " + i);
for (var j = 0; j < i; j++) {
alert("in for" + j + "Series" + (j+1)); //This alert is being executed..
dynamicTicks.push({
v: j, /*cData[j].c[0].v */
f: 'Series ' + (j + 1)
});
}
$scope.chart.data.rows = weekRows;
},
}
$scope.loadMyChart();
}]);
When used the statement cData[j].c[0].v, following error is displayed on browser console and no chart is shown on UI.
angular.min.js:sourcemap:119 TypeError: Cannot read property 'c' of undefined
wouldn't you build dynamic ticks where the chart data and options are created?
something like...
var createChart = function (rows, label) {
return {
"type": "ColumnChart",
"data": {
"cols": [
{"id": label, "label": label, "type": "number"},
{"id": "count", "label": "count", "type": "number"},
{"id": "pizza", "label": "Pizza", "type": "number"},
{"id": "softdrink", "label": "Softdrink", "type": "number"}
],
"rows": rows
},
"options": {
"title": label,
"isStacked": "true",
focusTarget: 'category',
hAxis: {
baselineColor: 'transparent',
gridlines: {
color: 'transparent'
},
slantedText: false,
"ticks": dynamicTicks,
},
tooltip: {
text: 'value'
}
}
}
};
var data = [
{"c":[{"v": 0, "f":"Jan - July"},{"v":63},{"v":"30"},{"v":"33"}]},
{"c":[{"v": 1, "f":"Aug - Sept"},{"v":70},{"v":"35"},{"v":"35"}]},
{"c":[{"v": 2, "f":"Oct - Dec"},{"v":80},{"v":"40"},{"v":"40"}]}
];
var dynamicTicks = [];
for (var i = 0; i < data.length; i++) {
dynamicTicks.push({
v: data[i].c[0].v,
f: 'Series ' + (i + 1)
});
}
$scope.myChart = createChart(data, "Data Series");
I have a simple Highcharts pie chart that takes the following data as input:
data: [
{"y":4, "name":"Russia", "txt": "Our hotel at the countryside was very nice and welcoming."},
{"y":2, "name":"Australia", "txt": "The trip to Ayers Rock was one of the highlights of our trip. The Great Barrier Reef and its clear water were simply amazing!"},
{"y":1, "name":"Argentina", "txt": "It has been a childhood dream to just go into the wild."},
{"y":4, "name":"China", "txt": "in year 1930 it was this is just a silly simple text to check if everything here is working."},
{"y":2, "name":"Neverland", "txt": "in year 1940 it was like this."},
{"y":4, "name":"Mars", "txt": "in year 1900 it was like this."}
]
Example:
$(document).ready(function() {
//var colors = ['#8d62a0', '#ceb3d8', '#d5dddd'];
Highcharts.getOptions().plotOptions.pie.colors = (function () {
var colors = [],
base = '#801a00',
i;
for (i = 0; i < 100; i += 1) {
colors.push(Highcharts.Color(base).brighten((i - 3) / 15).get());
}
return colors;
}());
var chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'pie'
},
tooltip: {
formatter: function() {
return '<b>'+this.point.name+'</b>';
}
},
legend: {
enabled: false
},
plotOptions: {
pie: {
innerSize: '75%'
},
series: {
cursor: 'pointer',
point: {
events: {
click: function(){
defineInnerData(this.y, this.txt, this);
},
}
},
states: {
hover: {
enabled: false
}
}
}
},
yAxis: {
title: {
text: null
},
labels: {
enabled: false
}
},
series: [{
dataLabels: {
enabled: false
},
data: [
{"y":4, "name":"Russia", "txt": "Our hotel at the countryside was very nice and welcoming."},
{"y":2, "name":"Australia", "txt": "The trip to Ayers Rock was one of the highlights of our trip. The Great Barrier Reef and its clear water were simply amazing!"},
{"y":1, "name":"Argentina", "txt": "It has been a childhood dream to just go into the wild."},
{"y":4, "name":"China", "txt": "in year 1930 it was this is just a silly simple text to check if everything here is working."},
{"y":2, "name":"Neverland", "txt": "in year 1940 it was like this."},
{"y":4, "name":"Mars", "txt": "in year 1900 it was like this."}
]
}]
});
function defineInnerData(name, y, obj) { // on complete
var chart=$("#container").highcharts();
$( "#pieChartInfoText" ).remove();
var textX = chart.plotLeft + (chart.plotWidth * 0.5);
var textY = chart.plotTop + (chart.plotHeight * 0.5);
var span = '<span id="pieChartInfoText" style="position:absolute; text-align:block;left: 235px;top:210px;width: 150px; height: 180px; overflow: scroll;">';
span += '<span style="font-size: 11px">'+ y +'</span><br>';
span += '</span>';
$("#addText").append(span);
span = $('#pieChartInfoText');
span.css('left', textX + (span.width() * -0.5));
span.css('top', textY + (span.height() * -0.5));
span.css('overflow', 'auto');
}
defineInnerData("", "Click on the slices to see the text");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test</title>
<script src="http://code.highcharts.com/highcharts.js"></script>
</head>
<body>
<div>
<div id="container" style="position:absolute; left:0px; top:0px;"></div>
<div id="addText" style="position:absolute; left:0px; top:0px;"></div>
</div>
<script src="testfile_highcharts.js"></script>
</body>
</html>
My question now is: How would I read data as input that comes in a different structure like the json code below (its geoJSON), where I would like to get the following values as input for my chart:
The tooltip should show the name of the country (which corresponds to properties.name in the geoJSON).
The number of slices corresponds to the value of data.features.articles (which in turn corresponds to the number of sentences in data.features.text).
When clicking on a slice the corresponding sentence (from data.features.text) should be displayed in the center of the circle.
Here is how the geoJSON data looks like:
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"id": 4,
"properties": {
"id": 4,
"name": "Thailand",
"lat": "13.7538929",
"lon": "100.8160803",
"2005": 14
},
"geometry": {
"type": "Point",
"coordinates": [
"100.8160803",
"13.7538929"
]
},
"text": ["The official reason given was that he wanted to give the Thai people time to mourn his father before he became king.", "Thailand has rarely had what might be called routine royal successions. The last was 70 years ago, when the young King Ananda was found shot dead in his bedroom in still unexplained circumstances."],
"sentences": "2"
},
{
"type": "Feature",
"id": 7,
"properties": {
"id": 7,
"name": "the United States",
"lat": "38.8949549",
"lon": "-77.0366455",
"2005": 14
},
"geometry": {
"type": "Point",
"coordinates": [
"-77.0366455",
"38.8949549"
]
},
"text": ["The presidential elections will be a hard fight this year", "The best travelling season is September until end of October", "New York City is a must-see when travelling on the East Coast."],
"sentences": "3"
},
{
"type": "Feature",
"id": 8,
"properties": {
"id": 8,
"name": "Greece",
"lat": "37.9841493",
"lon": "23.7279843",
"2005": 14
},
"geometry": {
"type": "Point",
"coordinates": [
"23.7279843",
"37.9841493"
]
},
"text": ["The Aegean islands are little paradise spots not far away from the bustling capital Athens "],
"sentences": "1"
}
]
}
I've tried for hours now to get this working, but I cannot seem to be able to do it. I'm very new to JavaScript and would appreciate every help here. I'm also sorry if the explanation of my problems should not be entirely clear, but I hope that there is someone who can still help me...
The key point to accomplish this is to convert the json structured data to a javascript object in the strucuture you want.
For do this you should iterate over the json object, get the values you want and exports it to the list you're passing to chart.
// The empty list passed to chart
var dataToChart = [];
// Empty object of the list
var dataToChartObject = {"y":0, "name":"", "txt": ""}
// Iterate over jSon to populate dataToChartObject
$.each(jsonObject.features, function(index, value){
dataToChartObject.name = value.properties.name;
dataToChartObject.txt = value.text[0]
// I didn't realize what the articles number is, but do the same logic to get it
// Now let's insert the object to the list
dataToChart.push(dataToChartObject);
});
This can be done in by traversing the JSON object by its properties:
var featureSet = theJSON.features;
var theData = [];
for (var item in featureSet) {
var set = featureSet[item];
for (var theText in set.text) {
var theSlice = {};
theSlice.name = set.properties.name;
theSlice.y = set.text.length;
theSlice.txt = set.text[theText];
theData.push(theSlice);
}
}
Where theJSON is your returned JSON object. From here you modify the chart to use theData.
var chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'pie'
},
tooltip: {
formatter: function() {
return '<b>'+this.point.name+'</b>';
}
},
legend: {
enabled: false
},
plotOptions: {
pie: {
innerSize: '75%'
},
series: {
cursor: 'pointer',
point: {
events: {
click: function(){
defineInnerData(this.y, this.txt, this);
},
}
},
states: {
hover: {
enabled: false
}
}
}
},
yAxis: {
title: {
text: null
},
labels: {
enabled: false
}
},
series: [{
dataLabels: {
enabled: false
},
data: theData
}]
});
Sample jsFiddle. Note that your selector on which slice to pick is not happy due to multiple same name/value slices. I would add an index value to each slice and key off of that instead.
I have the following working code. It takes the input data and display the histogram based on a threshold.
"use strict";
var histograms,
thresholds = [];
var input_data = [{
"threshold": 1.5,
"histograms": [{
"sample": "Sample1",
"values": [{
"score": 6.7530200000000002,
"celltype": "Bcells"
}, {
"score": 11.432763461538459,
"celltype": "DendriticCells"
}, {
"score": 25.823089615384621,
"celltype": "Macrophages"
}, {
"score": 9.9911211538461551,
"celltype": "gdTCells"
}, {
"score": 7.817228076923076,
"celltype": "StemCells"
}, {
"score": 17.482806923076922,
"celltype": "StromalCells"
}, {
"score": 29.335427692307697,
"celltype": "Monocytes"
}, {
"score": 28.914959615384621,
"celltype": "Neutrophils"
}, {
"score": 13.818888461538467,
"celltype": "NKCells"
}, {
"score": 9.5030688461538464,
"celltype": "abTcells"
}]
}]
}, {
"threshold": 2,
"histograms": [{
"sample": "Sample1",
"values": [{
"score": 5.1335499999999996,
"celltype": "Bcells"
}, {
"score": 16.076072499999999,
"celltype": "DendriticCells"
}, {
"score": 46.182032499999998,
"celltype": "Macrophages"
}, {
"score": 6.5895700000000001,
"celltype": "gdTCells"
}, {
"score": 5.3218800000000002,
"celltype": "StemCells"
}, {
"score": 53.643625,
"celltype": "StromalCells"
}, {
"score": 85.1618225,
"celltype": "Monocytes"
}, {
"score": 55.559129999999996,
"celltype": "Neutrophils"
}, {
"score": 7.6717524999999984,
"celltype": "NKCells"
}, {
"score": 6.3277800000000006,
"celltype": "abTcells"
}]
}]
}];
processData(input_data);
function processData(data) {
histograms = data[0].histograms.map(function(data) {
return {
title: data.sample,
dataset: new Plottable.Dataset(),
dataByThreshold: {},
load: function(threshold) {
this.dataset.data(this.dataByThreshold[threshold]);
}
};
});
data.forEach(function(data) {
var threshold = data.threshold;
thresholds.push(threshold);
data.histograms.forEach(function(histogram, i) {
histograms[i].dataByThreshold[threshold] = histogram.values;
});
});
// Here we generalize the slide bar maximum threshold
$('#threshold').attr('max', thresholds.length - 1);
updateDatasets(thresholds[0]);
buildPlots();
updateThreshold();
}
$('#threshold').change(updateThreshold);
function updateThreshold() {
// This is where the user input updating slider
// takes place and where the QTIP is in action.
var thresholdIndex = parseInt($('#threshold').val(), 10);
$("#foldchange_threshold").html(thresholds[thresholdIndex]);
updateDatasets(thresholds[thresholdIndex]);
$(".tooltipped rect").qtip({
overwrite: true,
position: {
my: "bottom middle",
at: "top middle"
},
style: {
classes: "qtip-light"
}
});
}
function updateDatasets(threshold) {
histograms.forEach(function(histogram) {
histogram.load(threshold);
});
}
function buildPlots() {
var $histogramContainer = $('#sample-histograms');
histograms.forEach(function(histogram, index) {
var elementId = "sample-histogram-" + index;
$(document.createElementNS('http://www.w3.org/2000/svg', 'svg'))
.css({
width: '200px',
height: '200px',
display: 'inline-block'
})
.attr('id', elementId)
.appendTo($histogramContainer);
plotSampleHistogram(histogram.title, histogram.dataset, '#' + elementId);
});
}
function plotSampleHistogram(title, dataset, targetElement) {
var xScale = new Plottable.Scales.Category(),
yScale = new Plottable.Scales.Linear(),
colorScale = new Plottable.Scales.Color();
var xAxis = new Plottable.Axes.Numeric(xScale, "bottom"),
yAxis = new Plottable.Axes.Numeric(yScale, "left"),
titleLabel = new Plottable.Components.TitleLabel(title);
yScale.domainMin(0);
var plot = new Plottable.Plots.Bar()
.addDataset(dataset)
.x(function(d) { return d.celltype; }, xScale)
.y(function(d) { return d.score; }, yScale)
.attr("fill", function(d) { return d.celltype; }, colorScale)
.attr("title", function(d) { return '<div class="bartip">' + d.celltype + " (" + d.score.toFixed(2) + ') </div>'; })
.addClass("tooltipped");
new Plottable.Components.Table([
[null, titleLabel],
[yAxis, plot],
[null, xAxis]
]).renderTo(targetElement);
}
function drawHistogramLegend(targetElement) {
new Plottable.Components.Legend(colorScale)
.renderTo(targetElement);
}
<html>
<head>
<link href="https://cdnjs.cloudflare.com/ajax/libs/plottable.js/1.15.0/plottable.css" rel="stylesheet" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/qtip2/2.2.1/basic/jquery.qtip.css" rel="stylesheet" />
</head>
<body>
<!-- Display the sliding bar -->
<input id="threshold" type="range" min="0" max="1" step="1" value="0" />
<br>
<!-- Show foldchange threshold -->
<div id="foldchange_threshold" style="display: inline-block; align:center;"></div>
<!-- Show histograms -->
<div id="sample-histograms"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/plottable.js/1.15.0/plottable.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/qtip2/2.2.1/basic/jquery.qtip.js"></script>
</body>
</html>
If you run the code you can notice that the histogram will change as you drag the slider. AND a tool tip will appear if you place your mouse in one of the histogram bar.
The problem I'm facing is that the value of the tool tip does not change upon the user input to the sliding bar. For example with threshold=1.5 the Bcell score is 6.75 and threshold=2, the score is 5.13. This is not reflected in the tool tip.
How can resolve this issue?
It looks like QTip2 modifies the "title" attribute in some way, cacheing the previous information under "oldtitle". I got it to work by switching the title to a different attribute:
plot.attr("qtip2-title", function(d) {
return '<div class="bartip">' + d.celltype + " (" + d.score.toFixed(2) + ') </div>';
});
Then, we tell QTip2 to look up the "qtip2-title" property for the tooltip text:
$(".tooltipped .content rect").qtip({
// ... other setup here...
content: {
text: function() {
return $(this).attr("qtip2-title");
}
}
});
(Note the use of .content to avoid selecting unwanted rectangles).
Also, I noticed that currently xAxis is an Axes.Numeric, which will not work with Scales.Category. Use Axes.Category instead.
"use strict";
var histograms,
thresholds = [];
var input_data = [{
"threshold": 1.5,
"histograms": [{
"sample": "Sample1",
"values": [{
"score": 6.7530200000000002,
"celltype": "Bcells"
}, {
"score": 11.432763461538459,
"celltype": "DendriticCells"
}, {
"score": 25.823089615384621,
"celltype": "Macrophages"
}, {
"score": 9.9911211538461551,
"celltype": "gdTCells"
}, {
"score": 7.817228076923076,
"celltype": "StemCells"
}, {
"score": 17.482806923076922,
"celltype": "StromalCells"
}, {
"score": 29.335427692307697,
"celltype": "Monocytes"
}, {
"score": 28.914959615384621,
"celltype": "Neutrophils"
}, {
"score": 13.818888461538467,
"celltype": "NKCells"
}, {
"score": 9.5030688461538464,
"celltype": "abTcells"
}]
}]
}, {
"threshold": 2,
"histograms": [{
"sample": "Sample1",
"values": [{
"score": 5.1335499999999996,
"celltype": "Bcells"
}, {
"score": 16.076072499999999,
"celltype": "DendriticCells"
}, {
"score": 46.182032499999998,
"celltype": "Macrophages"
}, {
"score": 6.5895700000000001,
"celltype": "gdTCells"
}, {
"score": 5.3218800000000002,
"celltype": "StemCells"
}, {
"score": 53.643625,
"celltype": "StromalCells"
}, {
"score": 85.1618225,
"celltype": "Monocytes"
}, {
"score": 55.559129999999996,
"celltype": "Neutrophils"
}, {
"score": 7.6717524999999984,
"celltype": "NKCells"
}, {
"score": 6.3277800000000006,
"celltype": "abTcells"
}]
}]
}];
processData(input_data);
function processData(data) {
histograms = data[0].histograms.map(function(data) {
return {
title: data.sample,
dataset: new Plottable.Dataset(),
dataByThreshold: {},
load: function(threshold) {
this.dataset.data(this.dataByThreshold[threshold]);
}
};
});
data.forEach(function(data) {
var threshold = data.threshold;
thresholds.push(threshold);
data.histograms.forEach(function(histogram, i) {
histograms[i].dataByThreshold[threshold] = histogram.values;
});
});
// Here we generalize the slide bar maximum threshold
$('#threshold').attr('max', thresholds.length - 1);
updateDatasets(thresholds[0]);
buildPlots();
updateThreshold();
}
$('#threshold').change(updateThreshold);
function updateThreshold() {
// This is where the user input updating slider
// takes place and where the QTIP is in action.
var thresholdIndex = parseInt($('#threshold').val(), 10);
$("#foldchange_threshold").html(thresholds[thresholdIndex]);
updateDatasets(thresholds[thresholdIndex]);
$(".tooltipped .content rect").qtip({
overwrite: true,
position: {
my: "bottom middle",
at: "top middle"
},
style: {
classes: "qtip-light"
},
content: {
text: function() {
return $(this).attr("qtip2-title");
}
}
});
}
function updateDatasets(threshold) {
histograms.forEach(function(histogram) {
histogram.load(threshold);
});
}
function buildPlots() {
var $histogramContainer = $('#sample-histograms');
histograms.forEach(function(histogram, index) {
var elementId = "sample-histogram-" + index;
$(document.createElementNS('http://www.w3.org/2000/svg', 'svg'))
.css({
width: '200px',
height: '200px',
display: 'inline-block'
})
.attr('id', elementId)
.appendTo($histogramContainer);
plotSampleHistogram(histogram.title, histogram.dataset, '#' + elementId);
});
}
function plotSampleHistogram(title, dataset, targetElement) {
var xScale = new Plottable.Scales.Category(),
yScale = new Plottable.Scales.Linear(),
colorScale = new Plottable.Scales.Color();
var xAxis = new Plottable.Axes.Category(xScale, "bottom"),
yAxis = new Plottable.Axes.Numeric(yScale, "left"),
titleLabel = new Plottable.Components.TitleLabel(title);
xAxis.tickLabelAngle(-90)
yScale.domainMin(0);
var plot = new Plottable.Plots.Bar()
.addDataset(dataset)
.x(function(d) { return d.celltype; }, xScale)
.y(function(d) { return d.score; }, yScale)
.attr("fill", function(d) { return d.celltype; }, colorScale)
.attr("qtip2-title", function(d) { return '<div class="bartip">' + d.celltype + " (" + d.score.toFixed(2) + ') </div>'; })
.addClass("tooltipped");
new Plottable.Components.Table([
[null, titleLabel],
[yAxis, plot],
[null, xAxis]
]).renderTo(targetElement);
}
function drawHistogramLegend(targetElement) {
new Plottable.Components.Legend(colorScale)
.renderTo(targetElement);
}
<html>
<head>
<link href="https://cdnjs.cloudflare.com/ajax/libs/plottable.js/1.15.0/plottable.css" rel="stylesheet" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/qtip2/2.2.1/basic/jquery.qtip.css" rel="stylesheet" />
</head>
<body>
<!-- Display the sliding bar -->
<input id="threshold" type="range" min="0" max="1" step="1" value="0" />
<br>
<!-- Show foldchange threshold -->
<div id="foldchange_threshold" style="display: inline-block; align:center;"></div>
<!-- Show histograms -->
<div id="sample-histograms"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/plottable.js/1.15.0/plottable.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/qtip2/2.2.1/basic/jquery.qtip.js"></script>
<script src="histo.js"></script>
</body>
</html>
Hopefully this works for you! Glad to see you're using Plottable.
P.S. We're working on getting a more detailed tooltip tutorial for the website. Stay tuned.
I need to create a multi leveled that is dynamic because I have to drill down to hundreds or even thousands of data providers that will load from the database. The flow goes like this: I have 1, 2, 3, 4, and 5 years that will drill down to 16 Departments each and will drill down to Courses 10 or more courses. Doing it manually is tedious and I need it to be dynamic. Please help me.
The variables:
var ccs_final_data = AmCharts.loadJSON("<?php echo base_url();?>index.php/osa/final_ccs_data");
//VAR CCS AVERAGE_FINAL
var drill_down_to_ccs_courses_average_final = AmCharts.loadJSON("<?php echo base_url();?>index.php/osa/ccs_courses_data_average_final");
var drill_down_to_ccs_sections_BSIT_average_final = AmCharts.loadJSON("<?php echo base_url();?>index.php/osa/ccs_sections_data_BSIT_average_final");
var drill_down_to_ccs_sections_ACT_average_final = AmCharts.loadJSON("<?php echo base_url();?>index.php/osa/ccs_sections_data_ACT_average_final");
var drill_down_to_ccs_sections_BSCS_average_final = AmCharts.loadJSON("<?php echo base_url();?>index.php/osa/ccs_sections_data_BSCS_average_final");
The graph:
var chart2 = AmCharts.makeChart( "ccs2", {
"theme": "light",
type: "serial",
pathToImages: "http://cdn.amcharts.com/lib/3/images/",
dataProvider: ccs_final_data,
categoryField: "category",
categoryAxis: {
labelRotation: 0,
gridPosition: "start"
},
valueAxes: [ {
title: "CCS FINAL TERM - Passing"
} ],
graphs: [ {
valueField: "value",
colorField: "color",
type: "column",
lineAlpha: 100,
fillAlphas: 1
} ],
chartScrollbar: {
"updateOnReleaseOnly": true
},
chartCursor: {
bulletsEnabled: "enabled",
bulletSize: 15,
cursorAlpha: 100,
cursorColor: "#CC0000",
zoomable: true,
categoryBalloonEnabled: true
},
export: {
enabled: true
}
} );
Here's the drill down stuff:
chart2.addListener("clickGraphItem", function (event) {
if(event.item.category == "Average"){
event.chart.dataProvider = drill_down_to_ccs_courses_average_final;
event.chart.validateData();
chart2.addListener("clickGraphItem", function (event) {
if(event.item.category == "BSIT"){
event.chart.dataProvider = drill_down_to_ccs_sections_BSIT_average_final;
event.chart.validateData();
}
else if(event.item.category == "ACT"){
event.chart.dataProvider = drill_down_to_ccs_sections_ACT_average_final;
event.chart.validateData();
}
else if(event.item.category == "BSCS"){
event.chart.dataProvider = drill_down_to_ccs_sections_BSCS_average_final;
event.chart.validateData();
}
});
}
I'd say the best way to make it dynamic is to include some custom field for each data point in your data that would be passed in to server-side script so it knows which data to load.
I'm assuming your data looks like this now:
[ {
"category": "BSIT",
"value": 100
}, {
"category": "ACT",
"value": 200
}, {
"category": "BSCS",
"value": 150
} ]
You could easily add a third field to hold the information for drill-down data load:
[ {
"category": "BSIT",
"value": 100,
"drill": "ccs_sections_data_BSIT_average_final"
}, {
"category": "ACT",
"value": 200,
"drill": "ccs_sections_data_ACT_average_final"
}, {
"category": "BSCS",
"value": 150,
"drill": "ccs_sections_data_BSCS_average_final"
} ]
Then, when clickGraphItem event occurs, you could just take that info and pass it to load script dynamically:
chart2.addListener( "clickGraphItem", function( event ) {
if ( event.item.dataContext.drill !== undefined ) {
event.chart.dataProvider = AmCharts.loadJSON( "<?php echo base_url();?>index.php/osa/" + event.item.dataContext.drill );
event.chart.validateData();
}
} );
This way, you could have any number of drill-down levels, with each level data containing info about where to look for the data for the next level.
Also, I'm not sure as you haven't posted the code for it, so I'm assuming that AmCharts.loadJSON method is synchronous. If it's not (for example if you are using method from Data Loader), you will need to assign the chart's dataProvider after the data is loaded.