debugging domjs and highcharts - javascript

Ok, so I am attempting to move a fairly complex highcharts rendering script from the front end to server-side processing via nodejs
Its actually gone fairly well. I have "no errors" and the chart is rendering out with the data into svg. The problem is when I go to view the outputted svg in the browser its all messed up. In firebug I get the following "warning":
Unexpected value NaN parsing y attribute.
Unexpected value NaN parsing x attribute.
Unexpected value NaN parsing y attribute.
Unexpected value NaN parsing x attribute.
My question is, how can I go about debugging this? I have no idea where the NaN value is being calculated in highcharts source, and get no traditional js errors in the console. What is essentially the same code is currently working fine in an actual browser environment, but is failing when processed with nodejs and domjs, so its likely the issue has to do with that.
Here is my node script:
# base libs
{jsdom} = require 'jsdom'
jade = require 'jade'
fs = require 'fs'
# chart and settings
Chart = require './classes/Chart'
Config = require './config/config.base'
HighchartSettings = require './config/config.highchart
# curl -d "width=200px&height=100px&device=mobile&resolution=DAILY&type=areaSpline" http://localhost:8000/chart
app.post '/chart', (req, res) ->
# get post params
jadeOptions =
height : req.param('height', null)
width : req.param('width', null)
isEnglish = req.param 'isEnglish', true
resolution = req.param 'resolution', null
chartType = req.param 'type', null
device = if req.param('device', 'mobile') is 'mobile' then { mobile : true, tablet : false} else { mobile : false, tablet : true }
# render dom from jade
jade.renderFile 'views/chart.jade', jadeOptions, (err, html) ->
# setup virtual browser
dom = jsdom html
window = dom.createWindow()
{host} = req.headers
{document} = window
window.console.log = console.log
# get localization localization
window.localization = Localization isEnglish
# generate chart settings
configSettings = Config device, window.localization
configSettings = configSettings[resolution][chartType]
chartSettings = HighchartSettings device
# add jquery
jsdom.jQueryify window, 'http://'+host+'/jquery.1.7.2.min.js', ->
{$} = window
# add highcharts lib to virtual browser
highchartsjs = document.createElement 'script'
highchartsjs.type = 'text/javascript'
highchartsjs.src = 'http://'+host+'/highcharts.custom.js'
highchartsjs.onload = ->
{Highcharts} = window
# don't mess with me, highcharts will cut you!
Highcharts.setOptions
global :
useUTC : true
chartDailyJSONDummy = JSON.parse 'there is real json here, I have removed it for the sake of SO'
try
chart = new Chart configSettings, chartSettings, chartDailyJSONDummy, Highcharts, ->
output = $('#chartWrapper').html()
res.setHeader "Content-Type", "text/html"
res.write output
res.end()
console.log 'Chart sent \n'
catch err
console.log err
res.send 'error, see log \n'
document.body.appendChild highchartsjs
My highcharts configuration as displayed in the console:
{ chart:
{ renderTo: 'chartContainer',
backgroundColor: 'none',
events: { load: [Function] },
animation: false,
renderer: 'SVG' },
title:
{ text: 'Today vs Yesterday',
style: { color: 'white', fontSize: '17px', lineHeight: '22px' },
margin: 18,
y: 18 },
subtitle: { text: null },
xAxis:
{ type: 'datetime',
labels: { step: 12, formatter: [Function], style: [Object], y: 20 },
tickInterval: 3600000,
tickLength: 6,
tickWidth: 2,
startOnTick: true,
endOnTick: true,
maxPadding: 0 },
yAxis:
[ { title: [Object], labels: [Object] },
{ title: [Object], labels: [Object], linkedTo: 0, opposite: true } ],
legend: { enabled: false },
credits: { enabled: false },
tooltip: { enabled: false },
plotOptions:
{ areaspline:
{ color: '#19b6f4',
marker: [Object],
enableMouseTracking: false },
spline:
{ color: '#d01b7c',
marker: [Object],
enableMouseTracking: false } },
series:
[ { type: 'areaspline', data: [Object], animation: false },
{ type: 'spline', data: [Object], animation: false } ] }
UPDATE Here is a sample of the data that currently appears in series as [Object]
[ [ 1363562100000, 0.358 ],
[ 1363563000000, 0.498 ],
[ 1363563900000, 0.241 ],
[ 1363564800000, 0.211 ],
[ 1363565700000, 0.426 ],
[ 1363566600000, 0.58 ],
[ 1363567500000, 0.195 ],
[ 1363568400000, 0.217 ],
[ 1363569300000, 0.185 ],
[ 1363570200000, 0.19 ],
[ 1363571100000, 0.223 ],
[ 1363572000000, 0.18 ],
[ 1363572900000, 0.164 ],
[ 1363573800000, 0.188 ],
[ 1363574700000, 0.16 ],
[ 1363575600000, 0.166 ],
[ 1363576500000, 0.188 ],
[ 1363577400000, 0.154 ],
[ 1363578300000, 0.162 ],
[ 1363579200000, 0.1715 ],
[ 1363580100000, 0.1715 ],
[ 1363581000000, 0.173 ],
[ 1363581900000, 0.189 ],
[ 1363582800000, 0.151 ],
[ 1363583700000, 0.179 ],
[ 1363584600000, 0.288 ],
[ 1363585500000, 0.496 ],
[ 1363586400000, 0.175 ],
[ 1363587300000, 0.2 ],
[ 1363588200000, 0.185 ],
[ 1363589100000, 0.439 ],
[ 1363590000000, 1.19 ],
[ 1363590900000, 0.495 ],
[ 1363591800000, 0.294 ],
[ 1363592700000, 0.286 ],
[ 1363593600000, 0.28 ],
[ 1363594500000, 0.845 ],
[ 1363595400000, 2.055 ],
[ 1363596300000, 2.03 ],
[ 1363597200000, 1.611 ],
[ 1363598100000, 1.936 ],
[ 1363599000000, 1.499 ],
[ 1363599900000, 1.876 ],
[ 1363600800000, 1.699 ],
[ 1363601700000, 1.667 ],
[ 1363602600000, 1.862 ],
[ 1363603500000, 1.496 ],
[ 1363604400000, 2.312 ],
[ 1363605300000, 2.056 ],
[ 1363606200000, 0.878 ],
[ 1363607100000, 1.339 ],
[ 1363608000000, 0.69 ],
[ 1363608900000, 1.259 ],
[ 1363609800000, 0.884 ] ]
UPDATE 2 Issue does not seem to be caused by may highcharts configuration, but rather the jsdom environment missing some critical component. I suspect this because when using an older copy of highcharts, the problem isn't there, but then again my script is not structured for the older version and the chart renders with missing features.
2.0.5 WORKS
2.2.5 DOES NOT
project needs to be in 2.2.5
REALLY I JUST WANT A WAY TO DEBUG THIS

It's not possible for me to easily reproduce the issue, but here are some leads you might want to follow:
Highchart issue #1300:
Fixed error on exporting an empty chart due to labels with y attribute of NaN
There was some discussion about it on the Highsoft Forum.
This issue has been fixed in 2.3.5 as reported on their changelog.
It appears to be a warning when null data is received in most cases, so are you sure this data is returned? Maybe your chart is loaded before your object data is returned? I'm just thinking out loud.

This is not a solution, just a tip.
I think that you need to break this problem into a smaller one, make it work and increase it carefully. Them you will get where the thing is breaking your legs. Start fresh and redoo until you find the problem.

Related

How to create a RealTime ApexChart with vue

I am trying to follow the vue documentation on ApexCharts website.
https://apexcharts.com/vue-chart-demos/line-charts/realtime/
and the way they structured the component isn't practical. and seem like they have some missing methods in the example.
I wish to create a chart as in the example above that fetches data every second (1 second worth data)
<template>
<VueApexCharts
type="line"
height="350"
width="100%"
:options="chartOptions"
:series="series"
ref="chart"
/>
</template>
<script>
import { ref } from "vue";
import VueApexCharts from "vue3-apexcharts";
import { useStore } from "vuex";
export default {
name: "ChartApex",
components: { VueApexCharts },
props: ["session"],
setup(/* props */) {
let store = useStore();
let chartStream = undefined;
let series = [
{
name: "data1",
data: ref([]),
},
{
name: "data2",
data: [],
},
];
let chartOptions = {
chart: {
// id: "realtime",
width: "100%",
height: 350,
type: "line",
animations: {
enabled: true,
easing: "linear",
dynamicAnimation: {
speed: 1000,
},
},
toolbar: {
show: true,
},
zoom: {
enabled: true,
},
},
dataLabels: {
enabled: true,
},
stroke: {
curve: "straight",
},
title: {
text: "Chart",
align: "left",
},
grid: {
row: {
colors: ["#f3f3f3", "transparent"],
opacity: 0.5,
},
},
xaxis: {
type: "numeric",
show: true,
range: 3,
},
yaxis: {
min: -32768,
show: true,
max: 32768,
},
};
return {
chartOptions,
series,
store,
chartStream,
};
},
watch: {
"session.device.isDataStream"(newVal) {
if (newVal) this.startStream();
else this.endStream();
},
},
methods: {
startStream() {
console.log("starting chart stream");
this.chartStream = setInterval(() => {
// Push data
this.series[0].data.value.push(
...this.store.state.session.samples[0].at(-1)
);
}, 1000);
},
endStream() {
console.log("end chart srtrem");
clearInterval(this.chartStream);
},
},
};
</script>
I wish to display a range of 10 seconds on the X-axis (as in the example above).
When getting a new 1 second worth data: i would like my chart to show extra data and move one second ahead (x-axis) so it always remain as 10 seconds in total.
I am fetching data from my store which keeps updating in chunks. unfortunatly it stacks all in one chart that doesn't move. I wish to display one chunk every second.
I would prefer linking my data directly to the store variable. I am not doing this because i would need to use computed method, and i think it's less efficient (is it?)
the store.state.samples[0] is an array of chunks with around 1 second worth of data in each, structured as apex-charts use: [ts, sample] - looks like this:
// samples[0]
[
// Chunk 1 of almost a second
// [0] =>
[
[ // sample
8.75,
0
],
[ // sample
17.5,
-1
],
[ // etc
26.25,
-2
],
[
35,
-3
],...
],
[ // Chunk 2 of almost a second.
[
958.6875,
-12747
],
[
962.375,
-12808
],
[
966.0625,
-12789
],...
]
]
so that basically i push a chunk worth a second to my chart (..every second)
A lot recommend on apex-charts as a go-to charts library for vue, but seems they lack of proper documentation.
-
Here is link to the source code of the sample. Check there how it was built.
To show the range of 10 seconds use the xaxis.range setting:
const TICKINTERVAL = 1000;
const XAXISRANGE = 10000;
const ARRAYLENGTH = XAXISRANGE / TICKINTERVAL + 1;
xaxis: {
type: 'datetime',
range: XAXISRANGE,
position: 'bottom',
To move the X-Axis you should slice you data array, like the resetData() function does:
function resetData(){
data = data.slice(data.length - 10, data.length);
}
I did it with my ARRAYLENGTH constant
data.push(...new Data...);
if (data.length > ARRAYLENGTH) data = data.slice(-ARRAYLENGTH);

javascript show " instead of double quots

I want to show a line chart in my page by javascript.
sample code for showing chart is same as below
new Chartist.Line('#chart-with-area', {
labels: ["d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8"],
series: [
[5, 9, 7, 8, 5, 3, 5, 4]
]
}, {
low: 0,
showArea: true,
plugins: [
Chartist.plugins.tooltip()
]
});
I am using laravel framework and I need to send data from php to javascript.
I created two arrays, one for labels and one for data.
The problem is that when I add array for labels , I faced with below errors
htmlspecialchars(): Argument #1 ($string) must be of type string, array given
and when I send json , javascript change double quots
new Chartist.Line('#chart-with-area', {
labels: ["2021\/7\/5","2018\/11\/17","2019\/1\/8","2018\/10\/25","2019\/4\/9","2018\/11\/18","2019\/3\/11","2019\/1\/3","2019\/1\/5","2018\/12\/17","2021\/5\/25","2018\/12\/31"],
series: [[1,1,1,1,1,1,1,3,1,1,2,6]]
}, {
low: 0,
showArea: true,
plugins: [
Chartist.plugins.tooltip()
]
});
here is my code:
new Chartist.Line('#chart-with-area', {
labels: {{json_encode($requestLineChartLabel)}},
series: [{{json_encode($requestLineChartData,JSON_NUMERIC_CHECK)}}]
}, {
low: 0,
showArea: true,
plugins: [
Chartist.plugins.tooltip()
]
});
I searched a lot, but can't find any solution.
If you're using Laravel 7 or higher, you can use the #json blade directive to properly output json:
labels: #json($requestLineChartLabel),
series: [#json($requestLineChartData,JSON_NUMERIC_CHECK)]
Just make sure that those variables are not already json, or else you'll be double encoding it.

highcharts error 17 when creating a heatmap

I'm trying to generate a heatmap using data inserted by gon.
The frame for the chart is generated correctly in the browser, but the chart is missing, just blank.
and in the console I get:
Uncaught Highcharts error #17: www.highcharts.com/errors/17
which seems to be generated by the initSeries method in highcharts after a comment mentioning:
// No such series type
I'm using RoR4, with this in the Gemfile:
gem "highcharts-rails", "~> 3.0.0"
and this in the application.js:
//= require jquery
//= require jquery_ujs
//= require tether
//= require bootstrap-sprockets
//= require highcharts
//= require highcharts/highcharts-more
//= require turbolinks
//= require_tree .
my SLIM:
td
.card
.card-img-top(data-template-chart=true data-id=template.to_param)
my includes (from the compiled HTML):
<script src="/assets/highcharts.self-d34c91baaad4188e2d81d954aa38de43ec4916882f39d2d908f86d47a6e942b0.js?body=1" data-turbolinks-track="true"></script>
<script src="/assets/highcharts/highcharts-more.self-995bc649d8f9f68a0bb6bfb3242b35a20c494d716164fa0c93a74630b291113b.js?body=1" data-turbolinks-track="true"></script>
Inspecting the "sources" in the browser I can see both files being loaded
my coffeescript:
$(window).bind 'page:change', ->
initPage()
initPage= ->
$('[data-template-chart]').each( ->
curId = $(this).data("id")
data = gon.templates[curId]
$(this).highcharts
chart:
height: 150
width: 150
title: text: ''
xAxis:
showLastLabel: false
tickLength: 16
yAxis:
title: text: null
labels: format: '{value}:00'
minPadding: 0
maxPadding: 0
startOnTick: false
endOnTick: false
tickPositions: [0, 6, 12, 18, 24]
tickWidth: 1
min: 0
max: 23
reversed: true
colorAxis:
stops: [
[0, '#3060cf']
[0.5, '#fffbbc']
[0.9, '#c4463a']
[1, '#c4463a']
]
min: -15
max: 25
startOnTick: false
endOnTick: false
# labels: format: value
series: [
{
type: 'heatmap'
data: csv: data
borderWidth: 0
nullColor: '#EFEFEF'
colsize: 24 * 365
}
]
)
I'm guessing the issue is with the highcharts-more library, which is being loaded in the browser, but it doesn't seem to be available, and I'm guessing it's a problem with the javascript generated by coffeescript.
This is the compiled version:
(function() {
var initPage, update_form;
$(function() {
return initPage();
});
$(window).bind('page:change', function() {
return initPage();
});
update_form = function() {
var chart, end_quote, extremes, start_quote;
chart = $('#template_chart').highcharts();
extremes = chart.xAxis[0].getExtremes();
start_quote = Math.ceil(extremes.min);
end_quote = Math.floor(extremes.max);
$('#template_match_start_quote_id').val(gon.ids[start_quote]);
return $('#template_match_end_quote_id').val(gon.ids[end_quote]);
};
initPage = function() {
$('select[flexible_select]').flexible_select();
return $('#template_chart').each(function() {
var categories, prices;
prices = gon.prices;
categories = gon.ids;
return $(this).highcharts({
chart: {
zoomType: "x",
events: {
redraw: function() {
return update_form();
}
}
},
title: {
text: null
},
xAxis: {
categories: categories,
labels: {
enabled: false
}
},
yAxis: {
title: {
text: "Price",
style: {
color: Highcharts.getOptions().colors[1]
}
},
opposite: true
},
tooltip: {
shared: true
},
legend: {
enabled: false
},
credits: {
href: "http://www.pattern4all.com",
text: "source: www.pattern4all.com"
},
series: [
{
name: "Price",
data: prices,
type: "line",
marker: {
enabled: false
},
tooltip: {
valuePrefix: "$"
},
style: {
color: Highcharts.getOptions().colors[1]
}
}
]
});
});
};
}).call(this);
Turns out that:
I needed to add
//= require highcharts/modules/heatmap
to my application.js I thought it was a redundant inclusion, but apparently it's not.
Also the GEM readme, at: https://github.com/PerfectlyNormal/highcharts-rails mentions to install: gem "highcharts-rails", "~> 3.0.0" but 3.0.0 is not the latest version, I updated the gem inclusion to: gem "highcharts-rails", "~> 4.1.9", which is currently the latest, and the problem seems fixed.
Even removing completely the version specification would work:
gem "highcharts-rails"
getting the project to use the latest version.
I'm going to make a pull request to update the readme.

Flot pie chart series name "undefined"

I am trying to display browser visits for my site using flot pie chart. Everything is working properly except the series name displays as undefined.
Data for the series is.
[
[
"Chrome",
"54"
],
[
"Firefox",
"51"
],
[
"Internet Explorer",
"9"
],
[
"Opera Mini",
"2"
],
[
"Safari",
"2"
]
]
and the JavaScript is
$('#browserVisits').css({
height: '300px',
width: '100%'
});
$.plot($('#browserVisits'), visits, {
series: {
pie: {
show: true
}
},
grid: {
hoverable: true,
clickable: true
},
legend: {
show: false
}
});
And the result for this series is like
Why the series name displays undefined instead of browser name?
What am I doing wrong and what can be the solution?
Thanks.
Well you just have to add formatter function in pie block as follows
label: {
show: true,
formatter: function(label,point){
return(point.label + '<br>'+ point.percent.toFixed(2) + '%');
}
}
Also i have created a sample fiddle for you take a look
http://jsfiddle.net/coolbhushans/03kd2mav/

How do I skip a datapoint in Highcharts without causing an interruption in the line of the chart?

Using Highcharts ...
I have a series of values that corresponds with a series of times. Sometimes, the data value is null on a specific time and no marker is placed on the chart, which is good, but the line gets interrupted and basically starts a new chart on the next value that is not null.
I would like to skip the null values on the chart, but still keep the time values and just connect the last non-null value to the next with a solid line.
I have tried skipping the entire index if the value is null, but then the time value is skipped as well.
I have replaced the null with 0, but obviously then the data points lands on the 0-axis.
This is my data:
for (i = 0; i < tpoints.length; i++)
{
var tc = cpoints[i];
var tf = fpoints[i];
var t = tpoints[i];
labels.push(t);
c.push(tc);
f.push(tf);
}
This is my chart config:
var config = {
type: 'line',
fill : false,
data: {
datasets: [{
data: f,
backgroundColor: [
color(window.chartColors.red).alpha(0.5).rgbString(),
],
label: '',
fill : false
},{
data: c,
backgroundColor: [
color(window.chartColors.blue).alpha(0.5).rgbString(),
],
label: '',
fill : false
}],
labels: labels
},
options: {
maintainAspectRatio: false,
responsive: true,
title: {
display: true,
text: title,
fontSize: 22
},
legend: {
position: "bottom",
display: false
},
scales: {
yAxes: [{
display: true,
scaleLabel: {
display: true,
labelString: 'T'
},
ticks: {
beginAtZero: true
}
}]
}
}
};
This creates the line-chart as expected (Color dots for each data point. Each data dot is then connected with a thin grey line.), but somewhere in the middle of the chart, if it receives a null value, the grey line gets cut and only displays again between two non-null values.
Any ideas on how i can connect the data point before the null with the data point after the null?
Enable the connectNulls option:
series: [{
data: [...],
connectNulls: true
}]
Live demo: http://jsfiddle.net/BlackLabel/fheb9yp5/
API Reference: https://api.highcharts.com/highcharts/series.line.connectNulls
can you show us how your data shows up? if the null values ​​have a meaning in your treatments I suggest you change the type of graph or replace the null values ​​by zero

Categories