JavaScript - iterating through an array for checking condition - javascript

I am creating a high charts graph that I would like to dynamically give the graph color to depending on the title of an object. I currently have an array graphData that has an object title.
I have 5 possible results of titles:
"LOW", "MEDIUM-LOW", "MEDIUM", "MEDIUM-HIGH", AND "HIGH"
I am now attempting to iterate through my array and assign a color depending on what title the index has.
My entire graph receives one color based off the last title of the array. I would like the color to effect each index of the array seperartely.
For example: if "MEDIUM-HIGH" is the last title in the array, my entire graph gets #DD5F0C
Here is my code:
Array:
graphData: [ […]
​
0: Object { title: "LOW", result: 62582 }
​
1: Object { title: "MEDIUM-LOW", result: 57758 }
​
2: Object { title: "LOW", result: 8795 }
​
3: Object { title: "HIGH", result: 262525 }
​
4: Object { title: "MEDIUM-HIGH", result: 167168 } ]
let graphColor = ""
for (i = 0; i < graphData.length; i++) {
if (graphData[i].title === "LOW") {
graphColor = "#0D6302"
} else if (graphData[i].title === "MEDIUM-LOW") {
graphColor = "#0B7070"
} else if (graphData[i].title === "MEDIUM") {
graphColor = "#DC9603"
} else if (graphData[i].title === "MEDIUM-HIGH") {
graphColor = "#DD5F0C"
} else if (graphData[i].title === "HIGH") {
graphColor = "#C50710"
}
}
HighCharts code :
Highcharts.chart('container', {
chart: {
type: 'bar'
},
title: {
text: "Bar Graph"
},
xAxis: {
},
yAxis: {
min: 0,
formatter: function() {
return this.value + "%";
},
title: {
text: '% of Total'
}
},
legend: {
reversed: false
},
plotOptions: {
series: {
stacking: 'normal'
}
},
series: [{
name: `graphData[0].title`,
color: graphColor,
data: [graphData[0]],
}, {
name: 'graphData[1].title',
color: graphColor,
data: [graphData[1]],
showInLegend: false,
linkedTo: ":previous"
}, {
name: 'graphData[2].title,
color: graphData[0].title,
data: [graphData[2]]
}, {
name: graphData[3].title,
color: '#DC9603',
data: [graphData[3]]
}, {
name: graphData[4].title,
color: graphColor,
data: [graphData[4]]
}, {
name: graphData[5].title,
color: graphColor,
data: [graphData[5]]
}]
});
I am expecting my "color" to be dynamically generated based off of what graphData.title equals for that specific index.

You are having trouble because you have graphData.length number of entries, but only one graphColor variable to hold the color. Your code samples don't look complete so I'll make some assumptions about how the surrounding code must be. I recommend building up your series data in the for-loop directly so you can just use it in the Highcharts.chart call. The code is easier to read that way and probably more flexible too if you need to have more data rows.
// build the series data array here so it's simple to use in the chart call
const series = new Array(graphData.length);
for (let i = 0; i < graphData.length; i++) {
let graphColor = "#000000"; // a default color just in case
// can use if/else or a switch here
if (graphData[i].title === "LOW") {
graphColor = "#0D6302";
} else if (graphData[i].title === "MEDIUM-LOW") {
graphColor = "#0B7070";
} else if (graphData[i].title === "MEDIUM") {
graphColor = "#DC9603";
} else if (graphData[i].title === "MEDIUM-HIGH") {
graphColor = "#DD5F0C";
} else if (graphData[i].title === "HIGH") {
graphColor = "#C50710";
}
series[i] = {
name: graphData[i].title,
color: graphColor,
data: [graphData[i].result]
};
}
// Adjust the series data as needed
series[1].showInLegend = false;
series[1].linkedTo = ":previous";
Highcharts.chart("container", {
chart: { type: "bar" },
title: { text: "Bar Graph" },
xAxis: {},
yAxis: {
min: 0,
formatter: function() {
return this.value + "%";
},
title: { text: "% of Total" }
},
legend: { reversed: false },
plotOptions: { series: { stacking: "normal" } },
series: series
});

Not sure if I've properly understood what are you trying to do, but try this way:
const colorMap = { "LOW":"#0D6302",
"MEDIUM-LOW": "#0B7070",
"MEDIUM": "#DC9603",
"MEDIUM-HIGH": "#DD5F0C",
"HIGH":"#C50710"
}
...
series: [{
name: `graphData[0].title`,
color: colorMap[graphData[0].title],
data: [graphData[0]],
}, {

In the Highchart way - you can iterate through the series after chart initialization and set the wanted colors by particular series.
Demo: https://jsfiddle.net/BlackLabel/6hm4ebna/
chart: {
type: 'bar',
events: {
load() {
let chart = this;
chart.series.forEach(s => {
console.log(s)
if (s.name === 'test1') {
s.update({
color: 'red'
})
}
else if (s.name === 'test3') {
s.update({
color: 'green'
})
}
})
}
}
},
API: https://api.highcharts.com/highcharts/chart.events.load
If this wouldn't help please reproduce your attempt with the sample data on the online editor which I could work on.

Related

Hide a category when a series name has no value attributed to it highchart

I have simplified my graph below for demo purposes but i have a lot of categories but not all series names will have a value of those categories. So when i select that series name how would i go about making 0 value categories disappear.
For example below when selecting person 1 the service 1 category should disappear instead of remain with no bars for it
Highcharts.chart('container', {
chart : {type: 'column'},
xAxis: {
categories: ["service1", "service2", "service3", "service"] ,
showEmpty : true ,
ordinal: false
},
series: [{
name: 'person1',
data: [0,2,3],
},
{ name : 'person2',
data: [10,6,5]
}]
});
link to the code https://jsfiddle.net/uroepk1j/
ppotaczek's Code from JSFiddle
Highcharts.chart('container', {
chart: {
type: 'column',
ignoreHiddenSeries: true
},
plotOptions: {
column: {
pointPlacement: null,
events: {
legendItemClick: function() {
var points = this.data,
hideCategory = false,
breaks = [],
stop,
series = this.chart.series;
this.chart.xAxis[0].update({
breaks: []
});
this.visible = !this.visible;
points.forEach(function(p, i) {
stop = false;
series.forEach(function(s) {
if (!stop && (!s.visible || s.data[i].y === 0)) {
hideCategory = true;
} else {
stop = true;
hideCategory = false;
}
}, this);
if (hideCategory) {
breaks.push({
from: i - 0.5,
to: i + 0.5,
breakSize: 0
})
}
hideCategory = false;
}, this);
this.visible = !this.visible;
this.chart.xAxis[0].update({
breaks: breaks
});
}
}
},
},
xAxis: {
categories: ['Col 1', 'Col 2', 'Col 3']
},
series: [{
name: 'person1',
data: [2, 0, 3],
},
{
name: 'person2',
data: [10, 1, 5]
}
]
});
Thanks for your help
You can use broken-axis module and insert breaks in place of the category in which there are no points, for example:
plotOptions: {
column: {
grouping: false,
pointPlacement: null,
events: {
legendItemClick: function() {
if (!this.visible) {
breaks[this.index] = {}
this.chart.xAxis[0].update({
breaks: breaks
});
} else {
breaks[this.index] = {
from: this.xData[0] - 0.5,
to: this.xData[0] + 0.5,
breakSize: 0
}
this.chart.xAxis[0].update({
breaks: breaks
});
}
}
}
},
}
Live demo: http://jsfiddle.net/BlackLabel/4utq7e3n/
API Reference: https://api.highcharts.com/highcharts/xAxis.breaks

Jquery - Counting JSON objects

Im building a chart system that will show me all data entries. I retrieve my data using ajax and I loop trough the data and group the results by colors (red, blue and yellow) and then divide them by months.
I setup base objects (dateCounts_Red, dateCounts_Blue and dateCounts_Yellow) so that by default it starts all months at 0. A counter would then add when it finds a match tot he apropriate color and month.
When I output my dateCounts I get:
{"2015":{"2015-12":1,"2015-10":null,"2015-08":null,"2015-11":null}}
{"2015":{"2015-12":0,"2015-10":null}}
{"2015":{"2015-12":0,"2015-10":null}}
Here is the code I have so far:
var dateCounts_Red = {"2015":{"2015-01":0,"2015-02":0,"2015-03":0,"2015-04":0},"2015":{"2015-05":0},"2015":{"2015-06":0},"2015":{"2015-07":0},"2015":{"2015-08":0},"2015":{"2015-09":0},"2015":{"2015-10":0},"2015":{"2015-11":0},"2015":{"2015-12":0}};
var dateCounts_Blue = {"2015":{"2015-01":0,"2015-02":0,"2015-03":0,"2015-04":0},"2015":{"2015-05":0},"2015":{"2015-06":0},"2015":{"2015-07":0},"2015":{"2015-08":0},"2015":{"2015-09":0},"2015":{"2015-10":0},"2015":{"2015-11":0},"2015":{"2015-12":0}};
var dateCounts_Yellow = {"2015":{"2015-01":0,"2015-02":0,"2015-03":0,"2015-04":0},"2015":{"2015-05":0},"2015":{"2015-06":0},"2015":{"2015-07":0},"2015":{"2015-08":0},"2015":{"2015-09":0},"2015":{"2015-10":0},"2015":{"2015-11":0},"2015":{"2015-12":0}};
data.d.results.forEach(function(element) {
var date = element.created_date.slice(0, 7);
var yr = date.slice(0, 4);
var Color = element.colorvalue;
if(Color == "red") {
dateCounts_Red[yr][date]++;
}
if(Color == "blue"){
dateCounts_Blue[yr][date]++;
}
if(Color == "yellow"){
dateCounts_Yellow[yr][date]++;
}
});
Red_yr_2015_data = [dateCounts_Red['2015']['2015-01'], dateCounts_Red['2015']['2015-02'], dateCounts_Red['2015']['2015-03'], dateCounts_Red['2015']['2015-04'], dateCounts_Red['2015']['2015-05'], dateCounts_Red['2015']['2015-06'], dateCounts_Red['2015']['2015-07'], dateCounts_Red['2015']['2015-08'], dateCounts_Red['2015']['2015-09'], dateCounts_Red['2015']['2015-10'], dateCounts_Red['2015']['2015-11'], dateCounts_Red['2015']['2015-12']];
Blue_yr_2015_data = [dateCounts_Blue['2015']['2015-01'], dateCounts_Blue['2015']['2015-02'], dateCounts_Blue['2015']['2015-03'], dateCounts_Blue['2015']['2015-04'], dateCounts_Blue['2015']['2015-05'], dateCounts_Blue['2015']['2015-06'], dateCounts_Blue['2015']['2015-07'], dateCounts_Blue['2015']['2015-08'], dateCounts_Blue['2015']['2015-09'], dateCounts_Blue['2015']['2015-10'], dateCounts_Blue['2015']['2015-11'], dateCounts_Blue['2015']['2015-12']];
Yellow_yr_2015_data = [dateCounts_Yellow['2015']['2015-01'], dateCounts_Yellow['2015']['2015-02'], dateCounts_Yellow['2015']['2015-03'], dateCounts_Yellow['2015']['2015-04'], dateCounts_Yellow['2015']['2015-05'], dateCounts_Yellow['2015']['2015-06'], dateCounts_Yellow['2015']['2015-07'], dateCounts_Yellow['2015']['2015-08'], dateCounts_Yellow['2015']['2015-09'], dateCounts_Yellow['2015']['2015-10'], dateCounts_Yellow['2015']['2015-11'], dateCounts_Yellow['2015']['2015-12']];
Im currently getting the following error from my Highcharts js:
Uncaught TypeError: Cannot set property 'index' of undefined
THis is preventing the chart system to work correctly the data returned is not being returned with it's expected data.
Here a full example to the issue https://jsfiddle.net/awo5aaqb/21/
Would anyone know what im missing?
Your date count objects have major structural flaw.
When you prettify them they look like:
var dateCounts_Blue = {
"2015": {
"2015-01": 0,
"2015-02": 0,
"2015-03": 0,
"2015-04": 0
},
"2015": {
"2015-05": 0
},
"2015": {
"2015-06": 0
},
"2015": {
"2015-07": 0
},
......
Object keys must be unique so these are clearly being repeated and the compiler will over write duplicates.
Fix the pattern that breaks away from the intended pattern grouping at the beginning
var dateCounts_Red = {
"2015":
{
"2015-01":0,
"2015-02":0,
"2015-03":0,
"2015-04":0,
"2015-05":0,
"2015-06":0,
"2015-07":0,
"2015-08":0,
"2015-09":0,
"2015-10":0,
"2015-11":0,
"2015-12":0
},
};
var dateCounts_Blue = {
"2015":{
"2015-01":0,
"2015-02":0,
"2015-03":0,
"2015-04":0,
"2015-05":0,
"2015-06":0,
"2015-07":0,
"2015-08":0,
"2015-09":0,
"2015-10":0,
"2015-11":0,
"2015-12":0
}
};
var dateCounts_Yellow = {
"2015":{
"2015-01":0,
"2015-02":0,
"2015-03":0,
"2015-04":0,
"2015-05":0,
"2015-06":0,
"2015-07":0,
"2015-08":0,
"2015-09":0,
"2015-10":0,
"2015-11":0,
"2015-12":0}
};
Your data structure is flawed and such comparing values when doing the foreach loop becomes inconsistent because it compares it to multiple values, the above JSON is the fix for your problem.
Not quite codereview.stackexchange.com, but I heavily modified your javascript to make it work a bit better
$.ajax({
url: basePath,
dataType: 'json',
cache: false,
success: function(data) {
var counts = {};
data.d.results.forEach(function(element) {
// If you know it's all the same year, you could totally ignore this
var yr = element.created_date.slice(0, 4);
var month = parseInt(element.created_date.slice(5,7));
var color = element.colorvalue;
if (counts[color] === undefined) {
counts[color] = {};
}
if (counts[color][yr] === undefined) {
counts[color][yr] = {};
}
current_value = counts[color][yr][month];
if (current_value === undefined) {
// Doesnt exist yet, so add it
counts[color][yr][month] = 1;
} else {
// Exists, so increment by 1
counts[color][yr][month] = current_value + 1;
}
});
console.log(JSON.stringify(counts));
console.log(transform_series(counts['red']['2015']));
console.log(transform_series(counts['blue']['2015']));
console.log(transform_series(counts['yellow']['2015']));
var Options = {
chart: {
renderTo: 'myfirstchart',
type: 'column',
margin: 75,
options3d: {
enabled: true,
alpha: 25,
beta: 0,
depth: 70
}
},
title: {
text: "Test Highcharts"
},
subtitle: {
text: 'Test charts'
},
plotOptions: {
column: {
depth: 25
}
},
xAxis: {
categories: ["Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"]
},
yAxis: {
title: {
text: "Number of entries"
}
},
tooltip: {
headerFormat: '<b>{point.key}</b><br>',
pointFormat: '<span style="color:{series.color}">\u25CF</span> {series.name}: {point.y} / {point.stackTotal}'
},
plotOptions: {
column: {
stacking: 'normal',
depth: 40
}
},
series: [{
name: 'Red',
color: 'red',
data: transform_series(counts['red']['2015']),
stack: '2015'
}, {
name: 'Blue',
color: 'blue',
data: transform_series(counts['blue']['2015']),
stack: '2015'
}, {
name: 'Yellow',
color: 'yellow',
data: transform_series(counts['yellow']['2015']),
stack: '2015'
}]
};
return new Highcharts.Chart(Options);
}
});
// this transforms the hash {10: 5, 11:1, 12:1} to get you all 12 months
// and returns an array of values [ 0, 0, 0, 0, 0 ... 5, 1, 1] that
// can be used in high charts
function transform_series(series) {
return Array.apply(null, Array(13)).map(function (_, i) {return (series[i] === undefined) ? 0 : series[i];}).slice(1,13);
}

Highcharts bar chart wont animate

Not sure why because I have done it in the past, but I have a Highcharts bar chart and it won't animate. This is the declaration of the chart,
function initializeData() {
$http.get(url).success(function(ret) {
$scope.jsondata = ret;
var newdata = [];
for (x = 0; x < 5; x++) {
newdata.push({
name: setName($scope.jsondata[x].name),
y: $scope.jsondata[x].data[0],
color: getColor($scope.jsondata[x].data[0])
});
}
$scope.chart.series[0].setData(newdata);
});
mainInterval = $interval(updateData, 5000);
}
function updateData() {
$http.get(url).success(function(ret) {
$scope.jsondata = ret;
console.debug("here");
for (x = 0; x < 5; x++) {
$scope.chart.series[0].data[x].update({
y: $scope.jsondata[x].data[0],
color: getColor($scope.jsondata[x].data[0])
});
}
});
}
$scope.chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'bar',
animation: true,
events: {
load: initializeData
}
},
title: {
text: ''
},
xAxis: {
type: 'category',
labels: {
style: {
fontSize: '11px'
}
}
},
yAxis: {
min: 0,
max: 100,
title: {
text: 'Total Score',
align: 'high'
}
},
legend: {
enabled: false
},
tooltip: {
pointFormat: 'Total Score <b>{point.y:.3f}</b>'
},
series: [{
name: 'Active Users',
data: [],
dataLabels: {
enabled: true,
rotation: 30,
style: {
fontSize: '10px',
fontFamily: 'Verdana, sans-serif'
},
format: '{point.y:.3f}', // one decimal
}
}]
});
And as you can see I have animate : true, so I am not sure what is the problem here. I have this older plunker where all of the data is in separate series, but it animates fine. But this is the plunker I am working on and having trouble with. They are like identical basically. In the newer one I broke out the initialization of data into its own method, but that is the only real main difference.
Some edits:
So as I was saying, I have done things this way with an areaspline chart (I know it was said they work a bit different but they are set up identically).
function initializeData() {
$interval.cancel(mainInterval);
$scope.previousPackets = '';
$http.get("https://api.myjson.com/bins/nodx").success(function(returnedData) {
var newdata = [];
var x = (new Date()).getTime();
for (var step = 9; step >= 0; step--) {
newdata.push([x - 1000 * step, 0]);
}
$scope.chart.series[0].setData(newdata);
});
mainInterval = $interval(updateData, 2000);
}
function updateData() {
$http.get(url + acronym + '/latest').success(function(returnedData) {
var x = (new Date()).getTime();
if ($scope.previousPackets != returnedData[0].numPackets) {
$scope.chart.series[0].addPoint([x, returnedData[0].numPackets], true, true);
$scope.previousPackets = returnedData[0].numPackets;
} else {
$scope.chart.series[0].addPoint([x, 0], true, true);
}
});
}
$scope.chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'areaspline',
animation: Highcharts.svg, // don't animate in old IE
marginRight: 10,
events: {
load: initializeData
}
},
title: {
text: ''
},
xAxis: {
type: 'datetime',
tickPixelInterval: 150
},
yAxis: {
title: {
text: 'Packets'
},
plotLines: [{
value: 0,
width: 1,
color: '#d9534f'
}]
},
tooltip: {
formatter: function() {
return Highcharts.numberFormat(this.y) + ' packets<b> | </b>' + Highcharts.dateFormat('%H:%M:%S', this.x);
}
},
legend: {
enabled: false
},
exporting: {
enabled: false
},
series: [{
name: 'Packets',
data: []
}]
});
I also updated the first chunk of code with the initializeData() method and updateData() method which are seemingly identical in both different charts.
It looks like it plays an important role if you provide your data at chart initialization or after. For simplicity I refactored your code a little
function initializeChart(initialData, onload) {
$scope.chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'bar',
animation: true,
events: {
load: onload
}
....
series: [{
name: 'Active Users',
data: initialData,
dataLabels: {
enabled: true,
format: '{point.y:.3f}', // one decimal
}
}]
});
}
function getData(callback) {
$http.get(url).success(function(ret) {
$scope.jsondata = ret;
var newdata = [];
for (x = 0; x < 5; x++) {
newdata.push([setName(ret[x].name), ret[x].data]);
}
callback(newdata);
});
}
As a result your two planks are in essense reduced to two methods below. The first initializes chart with preloaded data and the second updates data in existing chart.
function readDataFirst() {
getData(function(newdata) {
initializeChart(newdata);
});
}
function initializeChartFirst() {
initializeChart([], function() {
getData(function(newdata) {
$scope.chart.series[0].setData(newdata);
})
});
}
The first one animates fine while the second does not. It looks like highcharts skips animation if dataset is not initial and is treated incompatible.
However if you really want to have animation in your current plant (chart first workflow) you can achieve that by initializing first serie with zeros and then with the real data. This case it will be treated as update
function forceAnimationByDoubleInitialization() {
getData(function(newdata) {
initializeChart([]);
var zerodata = newdata.map(function(item) {
return [item[0], 0]
});
$scope.chart.series[0].setData(zerodata);
$scope.chart.series[0].setData(newdata);
});
All these options are available at http://plnkr.co/edit/pZhBJoV7PmjDNRNOj2Uc

Drilldown on multiple Highcharts with the same data

Is it possible to have Highcharts drilldown on multiple graphs that are sharing the same data when one graph is clicked?
As an example, I included a JSFiddle that uses the demo code (browser percentages).
http://jsfiddle.net/Pq6gb/
var gridster;
$(function(){
gridster = $(".gridster ul").gridster({
widget_base_dimensions: [150, 150],
widget_margins: [5, 5],
helper: 'clone',
resize: {
enabled: true,
stop: function(e, ui, $widget) {
for (var i = 0; i < Highcharts.charts.length; i++) {
Highcharts.charts[i].reflow();
}
}
}
}).data('gridster');
});
$(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: 'pie'
},
title: {
text: 'Browser market shares. November, 2013.'
},
subtitle: {
text: 'Click the slices to view versions. Source: netmarketshare.com.'
},
plotOptions: {
series: {
dataLabels: {
enabled: true,
format: '{point.name}: {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
}
})
}
});
});
$(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
$('#container2').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
}
})
}
});
});
There is a pie chart and a bar chart displaying the same data and can drilldown individually. I would like to click on any browser in the pie/bar chart and have both charts filter down to versions of that browser.
How would I go about doing this? Thanks.
Yes, it's possible. This is what you need to implement:
on drilldown event you can find respective point on a second chart and simple call 1point.doDrilldown()1
on drillup even in one chart, call on a second chart.drillUp()
Note: You need to be aware of infinite loop (for example drillUp() in one chart will call drillup event, which will drillUp() first chart again.. ) - just add some flag to call drillUp/doDrilldown only once per user click.

Highcharts visualize, style series

I'm using Highcharts.visualize to draw the graph from a table containing the data.
You can test my working code here: http://jsfiddle.net/S2XM8/1/
I have two questions:
I want to have a separate styling for my "Additional value". How do I go about it?
Can I add data for the X-axis via the javascript? For example if I need to fill in the gap between 2014-05-27 and 2014-05-25 in the table.
Highcharts.visualize = function (table, options, tableClass) {
// the categories
options.xAxis.categories = [];
$('tbody th', table).each( function () {
options.xAxis.categories.push(this.innerHTML);
});
// the data series
options.series = [];
$('tr', table).each( function (i) {
var tr = this;
$('.graph', tr).each( function (j) {
if (i === 0) { // get the name and init the series
options.series[j] = {
name: this.innerHTML,
data: []
};
} else { // add values
options.series[j].data.push(parseFloat(this.innerHTML));
console.log(this.innerHTML);
}
});
});
options.title = { text: 'Some graph' };
$('#' + tableClass + '-graph').highcharts(options);
};
var tableNumber = document.getElementById('rank-table'),
options = {
chart: {
zoomType: 'x'
},
xAxis: {
tickInterval: 30,
reversed: true,
labels: {
rotation: 45
},
type: 'datetime',
dateTimeLabelFormats: { // don't display the dummy year
month: '%e. %b',
year: '%b'
}
},
yAxis: {
title: {
text: 'Rank'
},
min: 1,
reversed: true
},
legend: {
layout: 'vertical',
align: 'middle',
verticalAlign: 'bottom',
borderWidth: 0
}
};
Highcharts.visualize(tableNumber, options, 'number');
Both things are possible, but require to modify visualize method, see: http://jsfiddle.net/S2XM8/4/
You can set series options in a chart and then merge with data:
series: [{
// nothing special
}, {
type: 'column' // set series type for example
}]
And merging:
options.series[j] = options.series[j] || {};
options.series[j].name = this.innerHTML,
options.series[j].data = [];
Check parsed value before passing as point value:
var value = parseFloat(this.innerHTML);
if(isNaN(value)) { //null value - produces NaN when parsing
options.series[j].data.push(10);
} else {
options.series[j].data.push(value); // push value to the series
}

Categories

Resources