Collapse Highcharts Organization Chart - highcharts

I'm using Highcharts to create organization charts as in provided example : https://jsfiddle.net/vegaelce/7rb6esqt/
Is it possible to add a "collapse" feature as in the Google organization chart ? In the following example https://jsfiddle.net/vegaelce/kb2gted4 when you double clic on "Mike" or "Jim" cell, it collapse all the cells above. I need to reproduce an equivalent mode with Highcharts, do you have an idea to do that ? (in Google API, the collapse mode is enabled via
allowCollapse:true
Thanks

There is no such built-in functionality in Highcharts, but you can add it by using click event and show/hide methods. Example:
plotOptions: {
series: {
point: {
events: {
click: function() {
const operateChildren = (point, operation) => {
point.linksFrom.forEach(link => {
link.graphic[operation]();
link.toNode.graphic[operation]();
operateChildren(link.toNode, operation);
});
};
if (this.linksFrom && this.linksFrom[0]) {
if (this.linksFrom[0].graphic.visibility === 'hidden') {
operateChildren(this, 'show');
} else {
operateChildren(this, 'hide');
}
}
}
}
}
}
},
tooltip: {
formatter: function(tooltip) {
if (this.point.graphic.visibility !== 'hidden') {
return tooltip.defaultFormatter.call(this, tooltip);
}
return false;
}
}
Live demo: https://jsfiddle.net/BlackLabel/dp03gq6a/
API Reference:
https://api.highcharts.com/class-reference/Highcharts.SVGElement#show
https://api.highcharts.com/class-reference/Highcharts.SVGElement#hide

Related

How to get points information when hovering over axis labels in highcharts using custom-events library?

I have a bar chart with labels. Is it possible to get the "points" data by hovering over said labels using custom-events library?
By points data I mean the variable from here:
tooltip: {
useHTML: true,
formatter(this: { points: any[] }) {
}
}
You can loop through all series points and match a point with a label position. Example:
xAxis: {
...,
labels: {
events: {
mouseover: function() {
const points = [];
this.axis.series.forEach(s => {
s.points.forEach(point => {
if (point.x === this.pos) {
points.push(point);
}
})
});
console.log(points);
}
}
}
}
Live demo: http://jsfiddle.net/BlackLabel/3xvgtw2c/

Highlight Highcharts Organization Chart nodes

I'm using Highcharts to create organization charts that where each node can be collapsed when clicked as in provided example : http://jsfiddle.net/vegaelce/83uktasc/
I would like to highlight the full path (from top level parent until the child node) when the mouse hover a node.
There is an example here : https://www.highcharts.com/blog/tutorials/how-to-use-an-org-chart-more-effectively/
I saw that the highlighting is provided in
#import 'https://code.highcharts.com/css/highcharts.css';
but it only highlights the first level parent.
How to achieve that ?
You can make the colors more bright in a similar way as the collapsing is implemented. Example:
const operateChildren = (point, operation) => {
point.linksFrom.forEach(link => {
operation([
link.toNode.graphic,
link.graphic,
link.toNode.dataLabel
]);
operateChildren(link.toNode, operation);
});
};
const hideElements = (elements) => {
elements.forEach(element => {
element.hide();
});
}
const showElements = (elements) => {
elements.forEach(element => {
element.show();
});
}
const highlighElements = (elements) => {
const color = elements[0].attr('fill');
elements[0].attr({
fill: Highcharts.Color(color).brighten(0.3).get()
});
};
Highcharts.chart('container', {
plotOptions: {
series: {
point: {
events: {
click: function() {
if (this.linksFrom && this.linksFrom[0]) {
if (this.linksFrom[0].graphic.visibility === "hidden") {
operateChildren(this, showElements);
} else {
operateChildren(this, hideElements);
}
}
},
mouseOver: function() {
if (this.linksFrom) {
highlighElements([this.graphic]);
operateChildren(this, highlighElements);
}
}
}
},
...
}
},
...
});
Live demo: http://jsfiddle.net/BlackLabel/s70ujvwy/
API Reference: https://api.highcharts.com/class-reference/Highcharts.Color

HighChart legend I override mouseover but loose transparency functionality. How do I keep it?

plotOptions: {
series: {
events: {
afterAnimate: function () {
for (let item of this.chart.legend.allItems) {
item.legendItem.on('mouseover', function (e) {
/**
* Register a callback based on the legend selected
*/
}).on('mouseout', function (e) {
/**
* Degerister a callback
})
}
}
},
I wish to add functionality when I mouseover the legend item but the above removes the default transparency functionality. How can I easily re-invoke?
You can add a part of default code for the events functions:
plotOptions: {
series: {
events: {
afterAnimate: function() {
const legend = this.chart.legend,
boxWrapper = legend.chart.renderer.boxWrapper;
for (let item of legend.allItems) {
let isPoint = item instanceof Highcharts.Point,
activeClass = 'highcharts-legend-' +
(isPoint ? 'point' : 'series') + '-active';
item.legendItem.on('mouseover', function(e) {
if (item.visible) {
legend.allItems.forEach(function(inactiveItem) {
if (item !== inactiveItem) {
inactiveItem.setState('inactive', !isPoint);
}
});
}
item.setState('hover');
if (item.visible) {
boxWrapper.addClass(activeClass);
}
}).on('mouseout', function(e) {
legend.allItems.forEach(function(inactiveItem) {
if (item !== inactiveItem) {
inactiveItem.setState('', !isPoint);
}
});
boxWrapper.removeClass(activeClass);
item.setState();
})
}
}
}
}
}
Live demo: http://jsfiddle.net/BlackLabel/6m4e8x0y/5000/

Highstock Angular value in legend

I'm looking for alternatives for the plug In values in legend.
The plug in uses jQuery and I'm running a Angular 5 application.
Has someone created a solution for that before?
labelFormat: '<span style="color:{color}">{name}</span>: <b>{point.y:.2f} USD</b> ({point.change:.2f}%)<br/>'
Here is a sample of Hicharts using jQuery to access the chart container and display the series value on legend.
To get rid of jquery you can replace jquery .bind method with js addEventListener on chart.container. Next, follow highcharts-angular documentation and create your own wrapper for this plugin. Check demo posted below.
Value-in-legend.js plugin:
(function(factory) {
if (typeof module === "object" && module.exports) {
module.exports = factory;
} else {
factory(Highcharts);
}
})(function(Highcharts) {
Highcharts.Series.prototype.point = {}; // The active point
Highcharts.Chart.prototype.callbacks.push(function(chart) {
chart.container.addEventListener("mousemove", function() {
var legendOptions = chart.legend.options,
hoverPoints = chart.hoverPoints;
// Return when legend is disabled (#4)
if (legendOptions.enabled === false) {
return;
}
if (!hoverPoints && chart.hoverPoint) {
hoverPoints = [chart.hoverPoint];
}
if (hoverPoints) {
Highcharts.each(hoverPoints, function(point) {
point.series.point = point;
});
Highcharts.each(chart.legend.allItems, function(item) {
item.legendItem.attr({
text: legendOptions.labelFormat
? Highcharts.format(legendOptions.labelFormat, item)
: legendOptions.labelFormatter.call(item)
});
});
chart.legend.render();
}
});
});
// Hide the tooltip but allow the crosshair
Highcharts.Tooltip.prototype.defaultFormatter = function() {
return false;
};
});
Next, initialize it in your component:
require("./path-to-your-file/value-in-legend")(Highcharts);
Demo:
https://codesandbox.io/s/j2j7wxwv7y

Change zIndex in HighChart

using Highchart, how can we change the zIndex for a line according to its state, or dynamically from a click event ?
I tried :
plotOptions: {
series: {
states: {
select: {
lineWidth: 2,
zIndex:10
}
},
with : this.setState(this.state === 'select' ? '' : 'select'); in the Click event but it doesn't work.
Alright, it's definitely not pretty, but I couldn't find a way to actually set the zIndex, so I had to do some maneuvering to fake it and bring each series to the front in a certain order. Here's the snippet to include:
Highcharts.Series.prototype.setState = (function (func) {
return function () {
if (arguments.length>0){
if (arguments[0] !== ''){
if (typeof this.options.states[arguments[0]]['zIndex'] !== 'undefined'){
this.options.oldZIndex = this.group.zIndex;
this.group.zIndex = this.options.states[arguments[0]]['zIndex'];
}
}else{
if (typeof this.options['oldZIndex'] !== "undefined"){
this.group.zIndex = this.options['oldZIndex'];
}
}
var order = [], i = 0;
$.each(this.chart.series, function(){
order.push({id:i,zIndex:this.group.zIndex,me:this});
i++;
});
order.sort(function(a,b){return (a.zIndex>b.zIndex) ? 1 : -1;});
$.each(order, function(){
this.me.group.toFront();
});
func.apply(this, arguments);
}
};
} (Highcharts.Series.prototype.setState));
And here's the JSFiddle demonstrating:
http://jsfiddle.net/G9d9H/9/
Let me know if that's what you needed.
I think a better solution is to set the series.group.toFront() method on click (I prefer to use it on mouseover)
plotOptions: {
series: {
events: {
click: function () {
this.group.toFront();//bring series to front when hovered over
}
}
}
}

Resources