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
}
}
}
}
Related
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
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/
When I call series[0].remove() in a while loop, the shadow of the cursor is never cleaned.
The code is called on a area-stacked click.
plotOptions: {
area: {
stacking: 'percent',
trackByArea: true,
events: {
click: function () {
var chart = $('#container').highcharts();
while(chart.series[0]) {
chart.series[0].remove();
}
}
}
}
}
JSFiddle : http://jsfiddle.net/4sV5g/
Any idea on how to avoid that ?
Found the solution here : https://stackoverflow.com/a/18659064/1456184
for(var i = chart.series.length - 1; i > -1; i--) {
if(chart.series[i].name !== 'Navigator') {
chart.series[i].remove(false);
}
}
Using remove(false) and then a redraw() will not have artifacts.
And I'm not removing the navigator series so there is no bug there too.
I should probably update it like in this fiddle : http://jsfiddle.net/engemasa/WcLQc/
High charts has double click event like?
plotOptions: {
series: {
cursor: 'pointer',
marker: {
radius: 2
},
point: {
events: {
// like this any event?If not, any alternative
dbclick: function () {
$('.highcharts-tooltip').show();
},
click: function () {
$('.highcharts-tooltip').show();
},
mouseOver: function () {
$('.highcharts-tooltip').hide();
},
mouseOut: function () {
$('.highcharts-tooltip').hide();
}
}
}
}
}
What i want to achieve is, i want to show tool tip on double click on point.
I tried using the extension, but it did not work, so I decided to write a small double click event (based on click event).
The downside is that it's encapsulated inside the 'click' event, but that's not a big issue since it calls a separate function.
First, define settings:
var doubleClicker = {
clickedOnce : false,
timer : null,
timeBetweenClicks : 400
};
Then define a 'double click reset' function in case the double click is not fast enough and a double click callback:
// call to reset double click timer
var resetDoubleClick = function() {
clearTimeout(doubleClicker.timer);
doubleClicker.timer = null;
doubleClicker.clickedOnce = false;
};
// the actual callback for a double-click event
var ondbclick = function(e, point) {
if (point && point.x) {
// Do something with point data
}
};
and in the highcharts settings of the chart:
series: [{
point: {
events: {
click: function(e) {
if (doubleClicker.clickedOnce === true && doubleClicker.timer) {
resetDoubleClick();
ondbclick(e, this);
} else {
doubleClicker.clickedOnce = true;
doubleClicker.timer = setTimeout(function(){
resetDoubleClick();
}, doubleClicker.timeBetweenClicks);
}
}
}
}
}]
You can use an extension, which allows do this.
http://www.highcharts.com/plugin-registry/single/15/Custom-Events
I used the capture of the variable as a double click parameter. And when true I cleaned the doubleclick.
series: {
cursor: 'pointer',
point: {
events: {
click: function () {
if (clickdouble == ('Category: ' + this.category + ', value: ' + this.y)) {
alert('Category: ' + this.category + ', value: ' + this.y);
clickdouble = '';
}else{
clickdouble = 'Category: ' + this.category + ', value: ' + this.y;
}
}
}
}
}
It works for me.
You can add an ondblclick event listener at the container's dom element in which you have the chart. Currently highcharts doesn't seem to handle the event so the event will simply propagate to the container.
I'm using jquery-ui tabs and jeditable to inline edit the tab title. But navigating with the cursors in the editable text leads jquery-ui to navigate to the tab next to it.
How can i prevent the jquery default behaviour (disable keyboad navigation in tabs).
Cheers,
Broncko
Solved it by:
$.widget( "ui.tabs", $.ui.tabs, {
options: {
keyboard: true
},
_tabKeydown: function(e) {
if(this.options.keyboard) {
this._super( '_tabKeydown' );
} else {
return false;
}
}
});
A better solution from here http://www.daveoncode.com/2013/09/18/how-to-disable-keyboard-navigation-in-jquery-ui-tabs/ :
jQuery('.foo').tabs({
activate: function(e, ui) {
e.currentTarget.blur();
}
});
It's possible to unbind keydown events when tabs are initialized:
$('#tabs').tabs({
create : function() {
var data = $(this).data('tabs');
data.tabs.add(data.panels).off('keydown');
}
});
Just had to do this myself. This is what worked for me:
$.widget("ui.tabs", $.ui.tabs, {
_tabKeydown: function (event) {
if (event.keyCode !== 38 && event.keyCode !== 40) {
this._super(event);
}
}
});
You can substitute any combination of keys using event.keyCode and even make it customizable with something like:
$.widget("ui.tabs", $.ui.tabs, {
options: {
overrideKeyCodes: [],
},
_tabKeydown: function (event) {
var isOverride = false;
if (Object.prototype.toString.call(this.options.overrideKeyCodes) === '[object Array]') {
for (i = 0; i < this.options.overrideKeyCodes.length; i++) {
if (event.keyCode === this.options.overrideKeyCodes[i]) {
isOverride = true;
break;
}
}
}
if (!isOverride) {
this._super(event);
}
}
});
$('#MyTabs').tabs({ overrideKeyCodes: [ 38, 40 ] });
Or even better you can add your own custom behaviors:
$.widget("ui.tabs", $.ui.tabs, {
options: {
overrideKeyCodes: {},
},
tabKeydown: function (event) {
if (this.options.overrideKeyCodes.hasOwnProperty(event.keyCode)) {
if (typeof this.options.overrideKeyCodes[event.keyCode] === 'function') {
this.options.overrideKeyCodes[event.keyCode](event, this._super(event));
}
}
else {
this._super(event);
}
}
});
$('#MyTabs').tabs({
overrideKeyCodes: {
40: function (event, callback) {
console.log(event.keyCode);
},
38: function (event, callback) {
console.log(event.keyCode);
if (callback) {
callback();
}
},
32: null //just let the space happen
}
});