Dygraphs not showing value - javascript

I'm rewriting a site that I made purely in PHP to a straight Javascript implementation. I moved all of my dygraphs code over, and the graph doesn't seem to show the value that you're hovering on anymore. The only thing that I can think of that is different, is that in the previous version, I used a PHP array, made a string out of it, and echo'ed it into a tag within my dygraph data declaration. In the new version, I'm using a native array call for the data. Might the formatters be screwing up here? The graph itself shows up, so it seems like the data is working.
I also noticed that the dygraphs Titles and Axes labels aren't showing up in the new one, despite the same code.
Old implementation:
g = new Dygraph(
document.getElementById("graphdiv"),
[[],[],[]....], //The whole array declaration couldn't be pasted here. Too big.
{
labels: labels.slice(),
title: 'cFIREsim Simulation Cycles',
ylabel: 'Portfolio ($)',
xlabel: 'Year',
labelsDivStyles: { 'textAlign': 'right' },
labelsDivWidth: 500,
labelsDiv: 'labelsdiv',
digitsAfterDecimal: 0,
yAxisLabelWidth: 100,
axes: {
y: {
labelsKMB: false,
maxNumberWidth: 11,
valueFormatter: function numberWithCommas(x) {
return 'Portfolio: $' + x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
},
axisLabelFormatter: function numberWithCommas(x) {
return '$' + x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
},
x: {
valueFormatter: function numberWithCommas(x) {
return 'Selected Year: ' + x;
},
},
},
showLabelsOnHighlight: true,
highlightCircleSize: 3,
strokeWidth: 1.5,
strokeBorderWidth: 0,
highlightSeriesBackgroundAlpha: 1.0,
highlightSeriesOpts: {
strokeWidth: 4,
strokeBorderWidth: 2,
highlightCircleSize: 5,
},
}
);
New Implementation:
Simulation.g.push(new Dygraph(
// containing div
document.getElementById("graph" + Simulation.tabs), //graph div has dynamic name for multiple graphs.
chartData, {
labels: labels.slice(),
title: 'cFIREsim Simulation Cycles',
ylabel: 'Portfolio ($)',
xlabel: 'Year',
labelsDivStyles: {
'textAlign': 'right'
},
labelsDivWidth: 500,
labelsDiv: 'labels' + this.tabs, //same dynamic names as graphdiv
digitsAfterDecimal: 0,
axes: {
y: {
axisLabelWidth: 100,
labelsKMB: false,
maxNumberWidth: 11,
valueFormatter: function numberWithCommas(x) {
return 'Spending: $' + x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
},
axisLabelFormatter: function numberWithCommas(x) {
return '$' + x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
},
x: {
valueFormatter: function numberWithCommas(x) {
return 'Year: ' + x;
},
},
},
showLabelsOnHighlight: true,
highlightCircleSize: 3,
strokeWidth: 1.5,
strokeBorderWidth: 0,
highlightSeriesBackgroundAlpha: 1.0,
highlightSeriesOpts: {
strokeWidth: 4,
strokeBorderWidth: 2,
highlightCircleSize: 5,
},
}
));

This ended up being a silly CSS issue. The labels div needed a CSS class so that I could actually SEE the labels on my black background.
.labels { color: black; }

Related

How do I create individual custom tooltips in an apex charts line chart in react?

I'm displaying a balance of a bank account over time. My goal is to have individual tool tips that show the balance AND the transaction that the balance change corresponds to.
I know I can format the Y value with a formatter, but after looking for a few hours I can't find a way to add data to each tool tip. For example the first tool tip might change the balance from 100 to 50, the tooltip would say 'credit card payment' the next tool tip might change the balance to 500 and the tool tip would say 'Paycheck'. here's what I'm doing in my options:
series: [{
name: 'Balance',
data: [
{
x: new Date('2018-02-12').getTime(),
y: 76
}, {
x: new Date('2019-02-12').getTime(),
y: 100
},
{
x: new Date('2020-02-12').getTime(),
y: 200
}, {
x: new Date('2021-02-12').getTime(),
y: 300
},
{
x: new Date('2022-02-12').getTime(),
y: 150
}, {
x: new Date('2023-02-12').getTime(),
y: 22
}
]
}],
options: {
chart: {
type: 'line',
stacked: false,
height: 380,
zoom: {
type: 'x',
enabled: true,
autoScaleYaxis: true
},
toolbar: {
autoSelected: 'zoom'
}
},
dataLabels: {
enabled: false
},
markers: {
size: 2,
},
title: {
text: 'Account balance over time',
align: 'left'
},
yaxis: {
labels: {
formatter: function (val) {
return val.balance;
},
},
title: {
text: 'Balance'
},
},
xaxis: {
type: 'datetime',
},
tooltip: {
shared: true,
y: {
formatter: function (val) {
return "$"+val;
}
}
}
},
Here is what the tooltips look like now:
Above the word 'balance' Id like it to say the actual transaction that's changing the balance. I'm wondering if this is possible at all with apex charts.
Have you tried these options from the docs: https://apexcharts.com/docs/options/tooltip/
There is a 'custom' function you can pass to create your own custom html
under the section called 'custom: function || Array of functions'
Here is the codepen they provide.
tooltip: {
custom: function({ series, seriesIndex, dataPointIndex, w }) {
return (
'<div class="arrow_box">' +
"<span>" +
w.globals.labels[dataPointIndex] +
": " +
series[seriesIndex][dataPointIndex] +
"</span>" +
"</div>"
);
}
}
Also, there is the 'formatter: function' where you can just provide a function to the formatter, similar to what you've already done.

On first time zooming data is missing in angular dygraph

When I zooming first time when graph is loaded, data is missing in angular dygraph. Here are screenshots
after zooming
Here is my code
function getPopUpGraph() {
$scope.currentZoom = 1;
$scope.popUpGraph = {};
$scope.popUpGraph = {
data: [],
options: {
labels: ["Date", $scope.selectedDataPoint.LegendName, "TrendLine"],
showPopover: false,
//customBars: true,
legend: "onmouseover",
highlightSeriesOpts: {
strokeWidth: 2,
strokeBorderWidth: 1
},
animatedZooms: true,
interactionModel: Dygraph.defaultInteractionModel,
showRangeSelector: true,
rangeSelectorPlotLineWidth: 1,
rangeSelectorPlotStrokeColor: 'gray',
rangeSelectorPlotFillColor: 'gray',
highlightCircleSize: 4,
rangeSelectorAlpha: 0.9,
rangeSelectorForegroundLineWidth: 1.25,
rangeSelectorForegroundStrokeColor: 'dark gray',
visibility: [true, false],
series: {
'TrendLine': {
strokePattern: [3, 2, 3, 2]
},
},
//xlabel: 'Date',
ylabel: $scope.selectedDataPoint.Unit,
title: $scope.selectedDataPoint.LegendName,
legendEnabled: false,
colors: ["#ff0000"],
valueRange: null,
height: 300,
resizeEnabled: true,
strokeWidth: 2,
axes: {
x: {
axisLabelFormatter: function (d, gran) {
if ($scope.currentZoomLevel.name == '12h') {
return $filter('date')(d, 'h:mm a');
}
else
return $filter('date')(d, 'MMM dd h:mm');
},
valueFormatter: function (ms) {
return $filter('date')(ms, 'M/d/yy h:mm a');
}
}
},
drawCallback: function (g, is_initial) {
if (g.dateWindow_)
myPopUpRange(g.dateWindow_)
}
}
}
$scope.getPopGraphData($scope.currentZoom, 0);
}
Data is fetching from $scope.getPopGraphData function.
Iam calling some other functions in this main function. I think this is not a problem. In angular dygraph's demo , after zooming , range selector also changing. So data is showing correctly. In my case range selector is not changing on first time zooming.
Any solution? Thanks in advance...
I found the solution. In getPopUpGraph() function , there is a drawback function is calling. On disable the myPopUpRange() function, it is now working properly. myPopUpRange() is used for resetting the x axis value. But there is no need, as dygraph automatically assign the x axis range.

How to create a column range chart in Highcharts using range and navigator functions?

I have a requirement to plot run history of a task in Highcharts. It needs to show that run history of the tasks as a horizontal bar. There are additional requirements which I've added as an update below. Recently I found out that inverted option is not supported in StockChart and that only navigator & rangeSelector are available in StockChart. Therefore I am using those functions.
So in order to achieve the requirement I created something similar to this jsfiddle example (found somewhere while browsing don't remember the source) and ended up with this plunker link with help from my previous question, thanks to Pawel Fus
Updating question to avoid confusion
Additional requirements:
Show only those tasks which ran in a particular date and time range. In case there are too many runs, such as more than 10 run, then there needs to be a way to display only 10 tasks visibly with a y-axis that is scrollable to show other tasks.
plunker link to the problem
Problem explanation of above plunker.
If you check the screenshot below from above plunker, the time range is from 12/12/2014 09:32:26 to 12/12/2014 10:32:26 and there are only 2 tasks that has run m_ARRAYV_SALES_ZIG1_CALL2_VOD__C_OB & m_ZIG2_HCP_MERGE_IB_CN. However I can see another task in between LILLY_C which did not even ran in this date time range. (In actual data there are more than 10 tasks that clutters this chart which does not even fall under this date time range)
Also if you notice at the bottom most right corner time shifted from 09:38 to 19:20. 19:20 is the end time for m_ZIG2_HCP_MERGE_IB_CN task.
Below is my chart options
var chart_options = {
chart: {
renderTo: 'container',
height: 600
},
title: {
},
credits: {
enabled: false
},
xAxis: {
type: 'datetime',
gridLineWidth: 1,
tickInterval: 1 * 3600 * 1000,
dateTimeLabelFormats: {
month: '%b %e, %Y'
}
},
yAxis: {
tickInterval: 1,
gridLineWidth: 1,
labels: {
formatter: function() {
if (tasks[this.value]) {
return tasks[this.value].name;
}
}
},
startOnTick: false,
endOnTick: false,
title: {
text: 'Task'
}
},
rangeSelector: {
selected: 0,
buttons: [ {
type: "minute",
count: 60,
text: "1h"
}, {
type: "minute",
count: 180,
text: "3h"
}, {
type: "minute",
count: 300,
text: "5h"
}],
inputDateFormat: '%m/%d/%Y %H:%M:%S',
inputEditDateFormat: '%m/%d/%Y %H:%M:%S',
inputBoxWidth: 120
},
navigator: {
enabled: false
},
legend: {
enabled: false
},
tooltip: {
shared: false,
formatter: function() {
var str = '';
str += 'Task: ' + this.series.name + '<br>';
str += 'From: ' + Highcharts.dateFormat('%m/%d/%y %H:%M', this.point.from) + '<br>';
str += 'To: ' + Highcharts.dateFormat('%m/%d/%y %H:%M', this.point.to) + '<br>';
return str;
}
},
plotOptions: {
line: {
lineWidth: 10,
marker: {
enabled: true
},
dataLabels: {
enabled: true,
align: 'left',
formatter: function() {
return this.point.options && this.point.options.label;
}
},
states:{
hover:{
lineWidth:10
}
}
},
series: {
cursor: 'pointer',
point: {
events: {
click: function () {
var query = '{ "task_id": "'+this.task_id+'","start_time": '+this.from+',"exclude_interval": '+opExcludeMinutes+',"size": 10 }';
$scope.taskName = this.series.name;
$scope.isTaskSelected = false;
$scope.operationalReportAgentTaskHistoryServiceRequest(query);
}
}
}
}
},
series: seriesData
};
So after a few hours of digging, I have just found out the culprit (or I really hope so). The problem is your definition of yAxis label formatter:
yAxis: {
tickInterval: 1,
gridLineWidth: 1,
labels: {
formatter: function() { // THIS IS THE PROBLEM
if (tasks[this.value]) {
return tasks[this.value].name;
}
}
},
startOnTick: false,
endOnTick: false,
title: {
text: 'Task'
}
},
You don't actually check if you should display the label according to task.intervals (see json.js). A simple update (Plunker) of the formatter seems to work:
yAxis: {
tickInterval: 1,
gridLineWidth: 1,
labels: {
formatter: function () {
console.log("scripts.js - yAxis.labels.formatter", this.value);
if (tasks[this.value]) {
//if (tasks[this.value].name === 'LILLY_C') {
var _xAxis = this.chart.axes[0];
var _task = tasks[this.value];
var _show = false;
// Not optimized for large collections
for (var _i = 0; _i < _task.intervals.length; _i++) {
var _int = _task.intervals[_i];
if (_xAxis.min <= _int.to) {
_show = true;
}
}
console.log("scripts.js - yAxis.labels.formatter",
tasks[this.value].name,
_show,
_xAxis.min,
_xAxis.max,
_task.intervals
);
if (_show) {
return tasks[this.value].name;
} else {
return;
}
//}
//return tasks[this.value].name;
}
}
},
startOnTick: false,
endOnTick: false,
title: {
text: 'Task'
}
},
See Plunker for demo.
Meaning of the yAxis labels is: Show label if you see a run in the graph or if there is a run on the right of the graph. Please modify the condition
if (_xAxis.min <= _int.to) {
as you see fit.
Disclaimer: I don't use Highcharts, so this answer tries to explain the problem and not to suggest a Highcharts-way of solving the problem.
Lessons learned:
yaxis-plugin.js is irrelevant to the problem.
Highstock.js is an open-source library (highstock.src.js). Any debugging is much easier if you debug original source code. Minified code adds unnecessary complexity and guessing. I have downloaded the library and added some console.log() to find out what is going on.

Flot Graph not plotting data

I a trying to plot some information using a flot graph but I can not get the values to appear on the graph. This code was part of a demo file included in a template and so i have modified it to plot the data rather than using a randomise for the values, i am getting no errors but the chart isn't working and was hoping somebody could point me in the right direction.
My code is here:
init: function()
{
// apply styling
charts.utility.applyStyle(this);
this.plot = $.plot(
$("#chart_simple"),
[{
label: "Jobs",
data: this.data.d1,
lines: {fillColor: "#dd3333"},
points: {fillColor: "#dd3333"}
},
{
label: "Resumes",
data: this.data.d2,
lines: {fillColor: "#282b30"},
points: {fillColor: "#282b30"}
}], this.options);
}
},
// lines chart with fill & without points
chart_lines_fill_nopoints:
{
// chart data
data:
{
d1: [[1,100], [2,150], [3,100]],
d2: [[1,100], [2,150], [3,100]]
},
// will hold the chart object
plot: null,
// chart options
options:
{
grid: {
show: true,
aboveData: true,
color: "#3f3f3f",
labelMargin: 5,
axisMargin: 0,
borderWidth: 0,
borderColor:null,
minBorderMargin: 5 ,
clickable: true,
hoverable: true,
autoHighlight: true,
mouseActiveRadius: 20,
backgroundColor : { }
},
series: {
grow: {active:false},
lines: {
show: true,
fill: true,
lineWidth: 2,
steps: false
},
points: {show:false}
},
legend: { position: "nw" },
yaxis: { min: 0 },
xaxis: {ticks:11, tickDecimals: 0},
colors: [],
shadowSize:1,
tooltip: true,
tooltipOpts: {
content: "%s : %y.0",
shifts: {
x: -30,
y: -50
},
defaultTheme: false
}
},
So, digging a bit, I see you are using javascript from here. Looking at a working example here, you've broken their code in the following ways:
1.) You no longer seem to have a parent charts object, so
charts.utility.applyStyle(this);
isn't going to work.
2.) The init function is part of the chart_lines_fill_nopoints object, in your cut/paste code it isn't anymore.
3.) In your sample code you never actually call the init function to draw the plot.
4.) In the options backgroundColor : { } is invalid for flot (maybe this is part of the missing charts.utility.applyStyle).
Taking all this into account here's a fiddle which makes this code work.
Generating flot plots with the above code feels unnecessarily convoluted. Perhaps it makes sense when using these templates, but if you just using this as an example of how to call flot it's not very straightforward.
Also, please next time you post a question, include all relevant information (like where you found this code and how you changed it). Taken out of context this code makes little sense.
This code is working
//Defining data for the chart
var data=
{
d1: [[1,100], [2,150], [3,100]],
d2: [[1,100], [2,150], [3,100]]
};
//Defining options for the chart
var options=
{
grid: {
show: true,
aboveData: true,
color: "#3f3f3f",
labelMargin: 5,
axisMargin: 0,
borderWidth: 0,
borderColor:null,
minBorderMargin: 5 ,
clickable: true,
hoverable: true,
autoHighlight: true,
mouseActiveRadius: 20,
backgroundColor : { }
},
series: {
grow: {active:false},
lines: {
show: true,
fill: true,
lineWidth: 2,
steps: false
},
points: {show:false}
},
legend: { position: "nw" },
yaxis: { min: 0 },
xaxis: {ticks:11, tickDecimals: 0},
colors: [],
shadowSize:1,
tooltip: true,
tooltipOpts: {
content: "%s : %y.0",
shifts: {
x: -30,
y: -50
},
defaultTheme: false
}};
// shorthand for document.ready
$(function(){
this.plot = $.plot(
$("#chart_simple"),
[{
label: "Jobs",
data: data.d1,
lines: {fillColor: "#dd3333"},
points: {fillColor: "#dd3333"}
},
{
label: "Resumes",
data: data.d2,
lines: {fillColor: "#282b30"},
points: {fillColor: "#282b30"}
}], this.options);
});
Check out the working example here on jsfiddle.

Dynamically adding multiple values to single point of bar graph in highchart

I was wondering if anyone knew of jsfiddle examples where stacked bar graphs with multiple values on a single point were changed after their creation. I've seen plenty of examples using setData for single points on a series, but none for multiple.
I currently have the following graphs and would like to put multiple values on each point.
window.jQuery(function () {
//var opportunities_by_month_chart;
opportunities_by_month_chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'column'
},
title: {
text: 'Pipeline By Month By Outcome'
},
subtitle: {
text: ''
},
xAxis: {
categories: ['test', 'test2']
},
yAxis: {
min: 0,
title: {
text: 'Opportunity size in £'
}
},
tooltip: {
formatter: function () {
return 'Month: ' + this.x + '<br/>' +
this.series.name + ': £' + this.y + '<br/>' +
'Total: £' + this.point.stackTotal;
}
},
plotOptions: {
series: {
stacking: 'normal'
}
},
credits: {
enabled: false
},
series: [{
name: 'Closed Won',
data: [],
color: 'green'
}, {
name: 'Closed Postponed',
data: [],
color: 'orange'
}, {
name: 'Closed Lost',
data: [],
color: 'red'
}, {
name: 'Other',
data: [],
color: 'blue'
}
]
});
});
http://jsfiddle.net/9FyGX/2/
If someone could point to an example or add an example to the jsfiddle it would make my day :D
As you said
chart.series[0].setData([1, 2, 3, 4], true);
chart.series[1].setData([2, 3, 4], true);
will work. However, the last parameter (true) tells highcharts to redraw the chart. Therefore it's more effecient to call the fist setData with false, and only redraw once you've finished adding the data.
chart.series[0].setData([1, 2, 3, 4], false);
chart.series[1].setData([2, 3, 4], true);

Categories

Resources