HighChart : plot line click event for multiple chart - javascript

I am using highchart for some drilldown functions.
I having a function to let the user click on an area plot and add a line. But then i found out my function has a bug in it. There's should be only one red line between those charts, but when the user click on the other chart the existing red line on the first chart is not removing.
The belowing is the function my charts sharing.
var myPlotLineId = "myPlotLine";
addPlotLine = function(evt) {
var point = evt.point;
var xValue = point.x;
var xAxis = point.series.xAxis;
Highcharts.each(xAxis.plotLinesAndBands, function(p) {
if (p.id === myPlotLineId) {
p.destroy();
}
});
xAxis.addPlotLine({
value: xValue,
width: 1,
color: 'red',
id: myPlotLineId
});
};
It should only allow one red line since i am using ID.
The below is the current situation.
Since i am using id for the plotline is shouldn't allow two line, please see my example:
http://jsfiddle.net/Xm4vW/74/
I want only ONE RED LINE in total out of many charts
UPDATE 1 :
I have tried redraw() in the new demo :
http://jsfiddle.net/Xm4vW/80/
but it doesn't help.
Please do let me know if the question is not clear enough.

There is nothing like 'Highcharts.each(xAxis.plotLinesAndBands, function(p) '. Iterate charts by loop and use 'removePlotLine(PlotLineID)' instead of 'destroy()':
for(i=0;i<Highcharts.charts.length; i++){
var chart=Highcharts.charts[i];
chart.xAxis[0].removePlotLine('myPlotLineId');
}
And set id in parenthesis:
id: 'myPlotLineId'
here is jsfiddle http://jsfiddle.net/asadsarwar89/bh4kz9rw/

Related

Can you remove specific grid lines and point labels using highcharts without css?

Currently I'm using css to remove my y-axis grid lines and labels like in the below image.
CSS:
.highcharts-yaxis-grid path:nth-child(1),.highcharts-yaxis-grid path:nth-child(2),
.highcharts-yaxis-grid path:nth-child(4),.highcharts-yaxis-grid path:nth-child(5){ stroke:transparent !important; }
.highcharts-yaxis-labels text:nth-child(1),.highcharts-yaxis-labels text:nth-child(2),
.highcharts-yaxis-labels text:nth-child(4),.highcharts-yaxis-labels text:nth-child(5){ fill:transparent !important; }
Whenever I download the chart as an image they reappear which makes sense as it doesn't see the css file I'm using.
I've tried to search for an answer on highcharts or anything on the net and haven't had luck, so here I am presenting this question.
For example in the load event you can remove specific labels and gridLines:
chart: {
events: {
load: function() {
var chart = this,
yAxis = chart.yAxis[0],
gridLines = yAxis.gridGroup.element.children,
ticks = yAxis.ticks,
tickPositions = yAxis.tickPositions;
gridLines[2].remove();
ticks[tickPositions[2]].label.element.remove();
}
}
}
Live demo: http://jsfiddle.net/BlackLabel/5m0s7th2/
API Reference: https://api.highcharts.com/highcharts/chart.events.load
Using the accepted answer I did this in a loop to avoid losing my middle gridline and tick val.
events: {
load: function() {
var chart = this,
yAxis = chart.yAxis[0],
gridLines = yAxis.gridGroup.element.children,
ticks = yAxis.ticks,
tickPositions = yAxis.tickPositions;
var i = 4;
while(i > -1){
if(i !== 2){
gridLines[i].remove(); // the whole array element is removed from gridLines, so we're doing this backwards
ticks[tickPositions[i]].label.element.remove();
}
i--;
}
}
}
It became a problem when I was starting from 0 using either the accepted answer or my loop. Hope this helps anyone who may have a ton of gridlines.

how to hide series data in combination high charts

I am using combine high charts. I need to hide a particular pie chart and column chart data while clicking a particular legend. If i use:
series[i].data[index].remove()
That removes the value but not able to show that value again while clicking the legend.
series[i].data[index].hide()
Refer to this JSFidddle - Example which I tried but I get an error like This is not function. How do I solve this?
You can use hide method on point SVG graphic element:
events: {
legendItemClick: function(e) {
var index = this.index;
var chart = this.series.chart;
var series = chart.series;
var len = series.length - 1;
if (this.visible) {
series[0].points[index].graphic.hide();
} else {
series[0].points[index].graphic.show();
}
}
}
Live demo: https://jsfiddle.net/BlackLabel/d8uaxefo/
API Reference: https://api.highcharts.com/class-reference/Highcharts.SVGElement#hide

Updating Series Color Appears to Break Navigator and Range Selector

We want to allow for the users to change the colors of the series from a monochrome-type gradient to divergent colors. We are doing this via a drop down menu and we capture their selection and do the update like below (simpler code than demo):
var rainbow = new Rainbow();
// Set start and end colors
rainbow.setSpectrum('#528bc2', 'white');
// Set the min/max range
var numSeries = chart.series.length;
var rangeLow = 0;
var rangeHigh = numSeries
rainbow.setNumberRange(rangeLow, rangeHigh);
// Loop over data and update the color value
for (index = 0; index < numSeries; ++index) {
if (chart.series[index].name != 'Navigator') {
if (chart.series[index].options.yAxis == 1) {
chart.series[index].update({
color: '#000080'
}, false);
} else {
chart.series[index].update({
color: '#' + rainbow.colourAt(index)
}, false);
}
if (chart.series[index].visible) {
var navigator = chart.get('nav');
navigator.setData(chart.series[index].options.data);
}
}
This does update the colors correctly and I can revert the change to use another list of colors in an array when the user wants to change back.
The chart is loaded up such that only one series is visible at a time and that series is used in the navigator series. When a user clicks on a series in the legend it hides the other series from being plotted and only shows the selected series, updates the navigator series, and updates the chart title. This works just fine when user does not change the color.
The issue I am facing is that when a user is on a series other than the initially loaded series when they change the color then the navigator series is reverted back to the series[0] data set because of chart.redraw() being called. How can I cleanly get the navigator series to be the currently visible series after calling the update code? I have tried putting this code (or similar block) after the color update and chart.events.load with no visible affect:
for (i = 0; i < this.series.length; i += 1) {
if (this.series[i].name != 'Navigator') {
if (this.series[i].visible) {
console.log(this.series[i].name);
var navigator = this.get('nav');
navigator.setData(this.series[i].options.data);
}
}
}
Here is a live set of data to work with in jsFiddle.
To reproduce issue let chart load, then click on 'Data Trend (%)' in legend so that it is visible in the chart. Notice that the navigator series has changed to be this series. Now, in the drop down change the selected value to "Multi-color". Notice how the series' color has changed, but so has the navigator series data.
Navigator has two properties which refer to series. The first one is its own series object - you update its data property, the second one is baseSeries which keeps reference to the main series from a chart.
http://jsfiddle.net/1jz3r78v/1/
If you set baseSeries to a visible series it works as you expected.
serie[i].show();
var navigator = this.chart.get('nav');
this.chart.scroller.baseSeries = this; // serie[i]
navigator.setData(serie[i].options.data);
this.chart.setTitle({
text: serie[i].name
});
Example: https://jsfiddle.net/yct6y11m/1/

Chart.js and right side free space

I wanted to ask, if there is a way to push chart to right side, so there will not be any free space. I attached simple image, red line show, that this space should be filled also by chart.
Also is possible to create vertical lines as dots ? I can't find answers to my questions, on official doc.
An this is my javsacript code:
var lineChartData = {
labels : ["January","February","March","April"],
datasets : [
{
label: "Dataset",
pointHighlightStroke : "rgba(220,220,220,1)",
data : [0,3,4,11]
}
]
};
window.onload = function(){
var ctx = document.getElementById("canvas").getContext("2d");
window.myLine = new Chart(ctx).Line(lineChartData, {
responsive: true,
scaleOverride: true,
scaleSteps: Math.ceil((max-start)/step),
scaleStepWidth: step,
pointDot : false,
});
}
The space is there because the last x axis label (April). Chart.js leaves enough space so that the label does not get clipped off. This also ensures that the tooltip for the last point shows without clipping off.
You could set the last (or all) labels to an empty string to get rid of the space. However, you won't see any labels in the tooltips. If you want to see the labels in the tooltips you need to extend the chart to remove the x axis labels like so
Chart.types.Line.extend({
name: "LineAlt",
initialize: function (data) {
var labels = data.labels;
data.labels = data.labels.map(function () { return '' });
Chart.types.Line.prototype.initialize.apply(this, arguments);
this.datasets[0].points.forEach(function (point, i) {
point.label = labels[i]
})
}
});
Note that you need to use LineAlt instead of Line.
Fiddle - http://jsfiddle.net/0u2c7tez/
However this will still clip off the tooltip for the last point. If you are going to enable tooltips and don't want them to be clipped off, then you need to use custom tooltips so that the tooltip is rendered in an external element (instead of the canvas) and not clipped off (see https://github.com/nnnick/Chart.js/blob/master/samples/line-customTooltips.html)

highstocks - legend position and refresh legend values on mousemove of multiple charts

Here is the scenario. I've multiple highstocks say 10 charts on a single page. Currently I've written 500 lines of code to position the legend, show tooltip and refresh the legend values on mousemove.
No. of legends vary per chart. On mousemove values of all the legends are updated. I need to optimize the code I am using highstocks v1.2.2.
Above screenshot shows 2 charts. Return, Basket, vs Basket Spread are legends and it's values are updated on every mousemove.
Please find this fiddle for example. In my case legends are positioned and updated values on mouse move with hundreds of lines of code. When I move the mouse the legend values of Return and Basket of first chart and the legend values of vs Basket Spread are updated. It's working fine but with lots of javascript code. So I need to optimize it less code or with highstocks built-in feature.
Update
User #wergeld has posted new fiddle. As I've shown in screenshot when cross-hair is being moved over any chart, the legend values of all the charts should be updated.
Is there anyway to implement the same functionality with less code or is there built-in feature available in highstocks ???
Using this as a reference.
Basic example would be to use the events.mouseover methods:
plotOptions: {
series: {
point: {
events: {
mouseOver: function () {
var theLegendList = $('#legend');
var theSeriesName = this.series.name;
var theYValue = this.y;
$('li', theLegendList).each(function (l) {
if (this.innerText.split(':')[0] == theSeriesName) {
this.innerText = theSeriesName + ': ' + theYValue;
}
});
}
}
}
}
}
This is assuming I have modded the <li> to be:
$('<li>')
.css('color', serie.color)
.text(serie.name + ': NA')
.click(function () {
toggleSeries(i);
})
.appendTo($legend);
You would then need to handle the mouseout event but I do not know what you want to do there.
Working example.
EDIT:
Here is a version using your reference OHLC chart to put the values in a different legend location when any point in the chart is hovered.
plotOptions: {
series: {
point: {
events: {
mouseOver: function () {
//using the ohlc and volumn data sets created at runtime.
var stockVal = ohlc[this.index][4]; // show close value
var stockVolume = volume[this.index][1];
var theChart = $('#container').highcharts();
var theLegendList = $('#legend');
$('li', theLegendList).each(function (l) {
var legendTitle = theChart.series[l].name;
if (l === 0) {
this.innerText = legendTitle + ': ' + stockVal;
}
if (l === 1) {
this.innerText = legendTitle + ': ' + stockVolume;
}
});
}
}
}
}
}

Categories

Resources