Adding new jqPlot charts to div dynamically makes the old ones empty - javascript

I have a div (overflow: auto) to which I dynamically add inner divs after a certain period. When a new one is added, it is added to the beginning. Each one of the inner divs have a jqPlot chart, and as long as there is just one it works fine, but as soon as another div is added two things happen with the old one(s):
The chart is moved further down in the div.
The chart has no plots or background (although it has axes marks).
According to the developer tools, all canvases are positioned correctly, but they are empty. This is the code used to add new charts (chart_div_? exists):
$.jqplot('chart_div_' + chartCounter, sold_plot, {
seriesColors: [ "#30D2FF", "BFFFCB", "BFFFCB", "BFFFCB" ],
seriesDefaults: {
showMarker: false,
markerOptions: {
show: false,
}
},
axes: {
xaxis: {
renderer: $.jqplot.DateAxisRenderer,
min: plot_min,
max: plot_max,
}
},
grid: {
background: '#444444',
},
});
chartCounter++;
Could it be something to do with moving a canvas? I tried redrawing it, but it did not work.

here is the example which can help you: Jsfiddle Link
HTML:
<div id="main">
<div id="chart1" style="margin-top:20px; margin-left:20px;"></div>
</div>
Click Here Trigger
Javascript:
$(document).ready(function () {
$.jqplot.config.enablePlugins = true;
var chartData = [
["19-Jan-2012", 2.61],
["20-Jan-2012", 5.00],
["21-Jan-2012", 6.00]
];
var cnt = 1;
// add a custom tick formatter, so that you don't have to include the entire date renderer library.
$.jqplot.DateTickFormatter = function (format, val) {
// for some reason, format isn't being passed through properly, so just going to hard code for purpose of this jsfiddle
val = (new Date(val)).getTime();
format = '%b&nbsp%#d'
return $.jsDate.strftime(val, format);
};
function PlotChart(chartData, extraDays, elem) {
var plot2 = $.jqplot(elem, [chartData], {
title: 'Mouse Cursor Tracking',
seriesDefaults: {
renderer: $.jqplot.BarRenderer,
rendererOptions: {
barPadding: 1,
barWidth: 50
},
pointLabels: {
show: true
}
},
axes: {
xaxis: {
pad: 1,
// a factor multiplied by the data range on the axis to give the
renderer: $.jqplot.CategoryAxisRenderer,
// renderer to use to draw the axis,
tickOptions: {
formatString: '%b %#d',
formatter: $.jqplot.DateTickFormatter
}
},
yaxis: {
tickOptions: {
formatString: '$%.2f'
}
}
},
highlighter: {
sizeAdjust: 7.5
},
cursor: {
show: true
}
});
}
PlotChart(chartData, 3, "chart1");
$("a.topopup").click(function () {
loading();
return false;
});
function loading() {
var div = $("#main");
cnt = cnt + 1;
var elemId = "chart" + cnt;
div.prepend("<div id='" + elemId + "'></div>");
PlotChart(chartData, 3, elemId);
}
});

Related

Highstock chart tooltip activation only when inside the chart

How to enforce that the tooltip show up only when mouse pointer is inside the chart area and not when on navigator scrollbar or on time range selectors in the top?
http://jsfiddle.net/1p4f5kny/
/*
The purpose of this demo is to demonstrate how multiple charts on the same page can be linked
through DOM and Highcharts events and API methods. It takes a standard Highcharts config with a
small variation for each data set, and a mouse/touch event handler to bind the charts together.
*/
$(function () {
/**
* In order to synchronize tooltips and crosshairs, override the
* built-in events with handlers defined on the parent element.
*/
$('#container').bind('mousemove touchmove touchstart', function (e) {
var chart,
point,
i,
event;
for (i = 0; i < Highcharts.charts.length; i = i + 1) {
chart = Highcharts.charts[i];
event = chart.pointer.normalize(e.originalEvent); // Find coordinates within the chart
point = chart.series[0].searchPoint(event, true); // Get the hovered point
if (point) {
point.highlight(e);
}
}
});
/**
* Override the reset function, we don't need to hide the tooltips and crosshairs.
*/
Highcharts.Pointer.prototype.reset = function () {
return undefined;
};
/**
* Highlight a point by showing tooltip, setting hover state and draw crosshair
*/
Highcharts.Point.prototype.highlight = function (event) {
this.onMouseOver(); // Show the hover marker
this.series.chart.tooltip.refresh(this); // Show the tooltip
this.series.chart.xAxis[0].drawCrosshair(event, this); // Show the crosshair
};
/**
* Synchronize zooming through the setExtremes event handler.
*/
function syncExtremes(e) {
var thisChart = this.chart;
if (e.trigger !== 'syncExtremes') { // Prevent feedback loop
Highcharts.each(Highcharts.charts, function (chart) {
if (chart !== thisChart) {
if (chart.xAxis[0].setExtremes) { // It is null while updating
chart.xAxis[0].setExtremes(e.min, e.max, undefined, false, { trigger: 'syncExtremes' });
}
}
});
}
}
// Get the data. The contents of the data file can be viewed at
// https://github.com/highcharts/highcharts/blob/master/samples/data/activity.json
$.getJSON('https://www.highcharts.com/samples/data/jsonp.php?filename=activity.json&callback=?', function (activity) {
$.each(activity.datasets, function (i, dataset) {
// Add X values
/*dataset.data = Highcharts.map(dataset.data, function (val, j) {
return [activity.xData[j], val];
});*/
$('<div class="chart">')
.appendTo('#container')
.highcharts('StockChart', {
chart: {
marginLeft: 40, // Keep all charts left aligned
spacingTop: 20,
spacingBottom: 20
},
title: {
text: dataset.name,
align: 'left',
margin: 0,
x: 30
},
credits: {
enabled: false
},
legend: {
enabled: false
},
xAxis: {
crosshair: true,
events: {
setExtremes: syncExtremes
},
labels: {
format: '{value} km'
}
},
yAxis: {
title: {
text: null
}
},
tooltip: {
positioner: function () {
return {
x: this.chart.chartWidth - this.label.width, // right aligned
y: -1 // align to title
};
},
borderWidth: 0,
backgroundColor: 'none',
pointFormat: '{point.y}',
headerFormat: '',
shadow: false,
style: {
fontSize: '18px'
},
shared: false,
valueDecimals: dataset.valueDecimals
},
series: [{
data: dataset.data,
name: dataset.name,
type: dataset.type,
color: Highcharts.getOptions().colors[i],
fillOpacity: 0.3,
tooltip: {
valueSuffix: ' ' + dataset.unit
}
}]
});
});
});
});
Insted of binding events on the container, you can use point mouseOver event to synchronize tooltips:
series: [{
point: {
events: {
mouseOver: function(e) {
for (i = 0; i < Highcharts.charts.length; i = i + 1) {
chart = Highcharts.charts[i];
if (chart !== this.series.chart) {
point = chart.series[0].points[this.index];
chart.tooltip.refresh([point]);
}
}
}
}
},
...
}]
Live demo: http://jsfiddle.net/BlackLabel/g0brx52d/
API Reference: https://api.highcharts.com/highcharts/series.line.point.events.mouseOver

Multiple Charts not moving in sync at random times when adding value on interval

I am trying to create dynamic number of series from UI. Upon selection, backend updates one entry at the time. While the graphs are running fine at most times. At some random time the two series move out of sync as in http://jsfiddle.net/cRgUr/
and come back in sync after few seconds. I have referred following links for resolution but still see the issue.
Chart not moving fluently when adding value to two lines on interval and Updating spline chart two lines on top of eachother
Below is the code snippet :
function getInitialData(series){
var arrayOfValues=[];
$http({
mode:'cors',
method:'GET',
url: '/getData',
headers: { 'Content-Type':'application/json' },
cache: false,
}).success(function(data) {
arrayOfValues.push(/*populated by backend*/); // E.g values for y for number of series selected. If 2 series are to be drawn, at a time this array will contain arrayOfValue[0]= y value for series 1, arrayOfValue[1]=y value for series 2
}
drawgraph(series,arrayOfValues,newWidgetMetrics/*widget selected from UI*/);
} ).error(function(data) {
});
function drawgraph(series,arrayOfValues,newWidgetMetrics1){
var time = (new Date()).getTime();
for(let p=0;p<arrayOfValues.length;p++){
if(p<arrayOfValues.length-1){
series[p].addPoint([time,arrayOfValues[p]] ,false
, (series[0].data.length >= 20));// set false for all series but the last, with an animation where we want the line to start plotting after 20 seconds
}
else{
series[p].addPoint([time,arrayOfValues[p]] , true
, (series[0].data.length >= 20));// set true for only the last series, with an animation where we want the line to start plotting after 20 seconds
}
chart.redraw();
}
arrayOfValues=[];
}
dataSeries=function(){
for(var i=0;i<length;i++){
var obj={};
obj.type="line";
obj.data=getData();
obj.boostThreshold=60;
obj.name=newWidgetLegends[i];
tArray.push(obj);
}
return tArray;
}
func_plot();
function func_plot(){
$(document).ready(function() {
Highcharts.setOptions({
global: {
useUTC: false
}
});
chart=Highcharts.chart(divId, {
chart: {
height:'38%',
zoomType: 'x',
type: 'spline',
animation: Highcharts.svg, // don't animate in old IE
marginRight: 10,
events: {
load: function () {
maxSamples = 60,
counter = 0;
// set up the updating of the chart each second
var ser = this.series;
// setTimeout(function () {
setInterval(function (){
window['arr' + count]=[];
getInitialData(ser);
}, 1000);
}, 2000);
}
}
},
title: {
text: '',
style: {
display: 'none'
}
},
exporting: {
buttons: {
contextButton: {
y:screen.height*-0.02
}
}
},
plotOptions: {
line: {
marker: {
enabled: false
}
},
events: {
legendItemClick: function () {
return false;
}
}
},
xAxis: {
type: 'datetime',
ordinal:false,
labels: {
format: '{value:%M:%S}'
},
tickInterval: 10000,
title: {
text: newWidetXLabel,
marginBottom: 100
}
},
yAxis: {
title: {
text:newWidetYLabel,
min: 0,
max:10
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}]
},
legend: {
title: {
text: '',
style: {
fontStyle: 'italic'
}
},
layout: 'horizontal',
align: 'right',
verticalAlign: 'top',
x: -30,
y: -17
},
boost: {
seriesThreshold:2,
useGPUTranslations: true
},
credits: {
enabled: false
},
tooltip: {
formatter: function () {
return Highcharts.dateFormat('%M:%S', this.x) + '<br/>' +
Highcharts.numberFormat(this.y, 2);
}
},
series: dataSeries()
});
});
}
$(window).resize(function() {
height = chart.height,
width = chart.width,
chart.setSize(width, height, doAnimation = false);
});
}
}
}]);
This issue happens because both series are not being drawn at the same moment. Second argument of the addPoint function is a flag that indicates whether the chart should be redrawn immediately after the addition or not. In your code 2 redraws happen instead of one. The update of the second series breaks the animation of the first one (it has no time to finish).
The solution here is to redraw the chart only after the second call of addPoint():
series.addPoint([x, y], false, true);
series2.addPoint([x, y2], true, true);
Live demo: http://jsfiddle.net/kkulig/5y1dacxv/
API reference: https://api.highcharts.com/class-reference/Highcharts.Series#addPoint

Remove Tooltip in Synchronized Charts, When user leaves the chart area

I am using Synchronized chart of Highcharts to demonstrate the statistics.
For reference : http://www.highcharts.com/demo/synchronized-charts.
Here, when the chart is getting plotted for the first time, no data points is selected. As, the cursor enters into the chart area, the tooltip, crosshairs and data points get highlighted. It works as expected.
The modification I need is, when the user comes out of the chart, the chart should look like as it was in the loading stage.
i.e. If the cursor is not on any of the chart,then no data points should remain selected. In other words, the tooltip, crosshair and the highlighted shadow on data point should get removed.
Thanks in advance for any help or suggestion.
use mouseleave to detect when the mouse is out of the container:
$('#container').bind('mouseleave', function(e) {
use hide method to hide the tooltip and hide Crosshair method to hide the crosshair:
chart.tooltip.hide(point);
chart.xAxis[0].hideCrosshair();
Check the example (jsfiddle):
$(function() {
$('#container').bind('mouseleave', function(e) {
var chart,
point,
i,
event;
for (i = 0; i < Highcharts.charts.length; i = i + 1) {
chart = Highcharts.charts[i];
event = chart.pointer.normalize(e.originalEvent);
point = chart.series[0].searchPoint(event, true);
point.onMouseOut();
chart.tooltip.hide(point);
chart.xAxis[0].hideCrosshair();
}
});
$('#container').bind('mousemove touchmove touchstart', function(e) {
var chart,
point,
i,
event;
for (i = 0; i < Highcharts.charts.length; i = i + 1) {
chart = Highcharts.charts[i];
event = chart.pointer.normalize(e.originalEvent); // Find coordinates within the chart
point = chart.series[0].searchPoint(event, true); // Get the hovered point
if (point) {
point.onMouseOver(); // Show the hover marker
chart.tooltip.refresh(point); // Show the tooltip
chart.xAxis[0].drawCrosshair(event, point); // Show the crosshair
}
}
});
/**
* Override the reset function, we don't need to hide the tooltips and crosshairs.
*/
Highcharts.Pointer.prototype.reset = function() {
return undefined;
};
/**
* Synchronize zooming through the setExtremes event handler.
*/
function syncExtremes(e) {
var thisChart = this.chart;
if (e.trigger !== 'syncExtremes') { // Prevent feedback loop
Highcharts.each(Highcharts.charts, function(chart) {
if (chart !== thisChart) {
if (chart.xAxis[0].setExtremes) { // It is null while updating
chart.xAxis[0].setExtremes(e.min, e.max, undefined, false, {
trigger: 'syncExtremes'
});
}
}
});
}
}
// Get the data. The contents of the data file can be viewed at
// https://github.com/highcharts/highcharts/blob/master/samples/data/activity.json
$.getJSON('https://www.highcharts.com/samples/data/jsonp.php?filename=activity.json&callback=?', function(activity) {
$.each(activity.datasets, function(i, dataset) {
// Add X values
dataset.data = Highcharts.map(dataset.data, function(val, j) {
return [activity.xData[j], val];
});
$('<div class="chart">')
.appendTo('#container')
.highcharts({
chart: {
marginLeft: 40, // Keep all charts left aligned
spacingTop: 20,
spacingBottom: 20
},
title: {
text: dataset.name,
align: 'left',
margin: 0,
x: 30
},
credits: {
enabled: false
},
legend: {
enabled: false
},
xAxis: {
crosshair: true,
events: {
setExtremes: syncExtremes
},
labels: {
format: '{value} km'
}
},
yAxis: {
title: {
text: null
}
},
tooltip: {
positioner: function() {
return {
x: this.chart.chartWidth - this.label.width, // right aligned
y: -1 // align to title
};
},
borderWidth: 0,
backgroundColor: 'none',
pointFormat: '{point.y}',
headerFormat: '',
shadow: false,
style: {
fontSize: '18px'
},
valueDecimals: dataset.valueDecimals
},
series: [{
data: dataset.data,
name: dataset.name,
type: dataset.type,
color: Highcharts.getOptions().colors[i],
fillOpacity: 0.3,
tooltip: {
valueSuffix: ' ' + dataset.unit
}
}]
});
});
});
});

Highstocks: How to define the span colors of a line instead of the individual line color

I am creating a Gantt Chart using Highstocks(compare multiple series).
1. I want to have the First span color to be Red, the second Blue and third Green.
How can I do the same?
2. how can i set the tooltip to show the values of all the points on the line instead of all points at the time.
3. How to fix y-axis and it should add scroll as values increase.
Please check the Gantt Chart Fiddle here.
var partNumber="2724070125R Planned,2724070125RActual,5511822432R Planned,5511822432RActual";
var partNum = partNumber.split(",");
var ganttData = [
[[Date.UTC(2013,11-1,07),1], [Date.UTC(2013,11-1,29),1], [Date.UTC(2013,11-1,30),1]],
[[Date.UTC(2013,11-1,20),1.25],Date.UTC(2013,11-1,21),1.25],Date.UTC(2013,12-1,21),1.25]],
[[Date.UTC(2013,11-1,13),2],[Date.UTC(2013,12-1,10),2],[Date.UTC(2014,02-1,14),2]],
[[Date.UTC(2013,11-1,21),2.25],[Date.UTC(2013,11-1,21),2.25],[Date.UTC(2013,11-1,30),2.25]]];
$( document ).ready(function(){
$(function() {
var seriesOptions = [],
yAxisOptions = [],
seriesCounter = 0,
names = partNum,
colors = Highcharts.getOptions().colors;
var data=ganttData;
$(function () {
$.each(names, function(i, name) {
seriesOptions[i] = {
// name: data[i][1],
name:name,
step:true,
data: data[i]
};
// As we're loading the data asynchronously, we don't know what order it will arrive. So
// we keep a counter and create the chart when all the data is loaded.
seriesCounter++;
if (seriesCounter == names.length) {
createChart();
}
});
});
// create the chart when all data is loaded
function createChart() {
Highcharts.setOptions({
global: {
useUTC: false
}
});
$('#ganttChart').highcharts('StockChart', {
chart: {
},
title: {
text: 'PPAP Cumulative Status'
},
rangeSelector: {
selected: 4
},
xAxis: {
type: 'datetime', ordinal: false //this sets the fixed time formats
},
yAxis: {
plotLines: [{
value: 0,
width: 2,
color: 'silver'
}],
min:0 },
plotOptions: {
series: {
lineWidth: 3,
states: {
hover: {
enabled: true,
lineWidth: 3
}
}
}
},
tooltip: {
pointFormat: '<span style="color:{series.color}">{series.name}</span>: <b>{point.y}</b><br/>',
valueDecimals: 0
},
series: seriesOptions,
exporting: {
enabled: false
}
});
}
});
});
1) You can set for series only one color. Here:
$.each(names, function(i, name) {
seriesOptions[i] = {
name: name,
step: true,
data: data[i],
color: 'yourColor'
};
...
});
2) In tooltip, you have access to series via this.points[0].series.data etc. So you can get all points.
3) Scroll is not supported.

jqplot tooltip Content Editor

I m Facing Problem in Displaying tool tip for jq plot bar chart
My jqPlot Code Is
<script class="code" type="text/javascript">
$(document).ready(function(){
var s1 = [0,10,20,30,40,50,60,70,80,90,100];
var s2 = [-100,-90,-80,-70,-60,-50,-40,-30,-20,-10,-0];
var ticks = ['01-jun','02-jun','03s-jun','04-jun','05-jun','06-jun','07-jun','08-jun','09-jun','10-jun'];
var plot1 = $.jqplot('chart1', [s1, s2], {
animate: !$.jqplot.use_excanvas,
stackSeries: true,
seriesDefaults:{
renderer:$.jqplot.BarRenderer,
rendererOptions: {fillToZero: true, barPadding: 10,barMargin: 15},
pointLabels: { show: true }
},
series: [
{ color: '#68BA38',label:'Uptime' },
{ color: 'red',label:'Downtime' },
{ label:'abcd' }
],
legend: {
show: true,
placement: 'outsideGrid'
},
axes: {
// Use a category axis on the x axis and use our custom ticks.
xaxis: {
pad: 1,
renderer: $.jqplot.CategoryAxisRenderer,
ticks: ticks
},
// Pad the y axis just a little so bars can get close to, but
// not touch, the grid boundaries. 1.2 is the default padding.
yaxis: {
pad: 1,
min:-100,
max: 100,
}
},
highlighter:{
show:true,
tooltipContentEditor:tooltipContentEditor
},
});
});
function tooltipContentEditor(str, seriesIndex, pointIndex, plot) {
// display series_label, x-axis_tick, y-axis value
return plot.series[seriesIndex]["label"] + ", " + plot.data[seriesIndex][pointIndex];
}
</script>
Its Displaying Tooltip like this: uptime,20 or downtime,-20
i Want To display Tooltip contain my tick value like: 01-jun
Had exactly this question myself, so I used Firefox's Web Developer tools to examine the plot object in the tooltipContentEditor function to find where the x-axis labels are. It is in plot.options.axes.xaxis.ticks. So the code you want to get your data point's x-axis label is:
plot.options.axes.xaxis.ticks[pointIndex]
This is the x-axis label for the point index in question.
My complete code for the callback function I now use is:
function tooltipContentEditor(str, seriesIndex, pointIndex, plot) {
return plot.series[seriesIndex]["label"] + ": " + plot.options.axes.xaxis.ticks[pointIndex] + ", " + plot.data[seriesIndex][pointIndex];
}
This shows the series label, the x-axis tick label, then the data point value.
I think it might be something like
return ticks[pointIndex];

Categories