Odd Behavior On Export Using NodeJS Module - javascript

Using the same code (see fiddle) and 3 different export URLs I get different export results. The issue is that the left side of the chart is clipping off the category titles but only if the export is JPG, PNG, or PDF - the SVG export is fine.
Current output for JPG, PNG, or PDF:
This the expected output for those types and what SVG does export:
I have set up a jsFiddle - click on the image types at the top to see the issues while changing the exporting.url value.
This is the export code:
window.chartExportLoc = function(chartid, exportType, graphHeader, graphFooter, marginSize) {
var chartToExport = $('#' + chartid).highcharts(),
sourceSpacingBottom = chartToExport.options.chart.spacingBottom;
if (!marginSize) {
marginSize = 15; //HighCharts default
}
chartToExport.exportChart({
type: exportType,
scale: 1,
filename: chartid
}, {
title: {
text: unescape(encodeURI(graphHeader)),
margin: marginSize
},
subtitle: {
y: 10,
text: unescape(encodeURI(graphFooter))
},
chart: {
shadow: false,
width: 800,
spacingBottom: sourceSpacingBottom - 20
}
});
return false;
}
We are running the highchart-export-server nodejs module and it is producing the clipped chart. If we change the exporting.url to use our existsing Java-based exporting application we get the correct/expected output. If we then change to use the export server hosted by highcharts (export.highcharts.com) it also produces the expected output.
I did file a bug on github for this issue but no responses from highcharts and hoping someone here can assist. This is preventing us from moving forward with the nodejs implementation and finally sunsetting the Java-based export app.

Related

How do you use functions in a different js file in phaser 3?

Im trying to create a js file with functions relevant to my game but i get an error message saying
Uncaught TypeError: Cannot read properties of undefined (reading 'add')
when i try to use phaser functions outside of the main file.
I have 2 files one called game.js and one called test.js. I am also using the matter physics engine.
game.js :
class bootScene extends Phaser.Scene {
//Preloading assets for later use
preload() {
this.load.image('linus', 'assets/linus.png');
this.load.script('t','test.js')
}
create() { }
update() {
//launch game scene
this.scene.launch('game').stop();
}
}
class playScene extends Phaser.Scene {
constructor() {
super('game');
}
create() {
test('test',1,1,'linus');
}
update() { }
}
// set the configuration of the game
let config = {
type: Phaser.WEBGL, // Phaser will use WebGL if available, if not it will use Canvas
width: 1280,
height: 720,
pixelArt: true,
transparent: false,
autoCenter: true,
backgroundColor: '#000000',
physics: {
default: 'matter',
matter: {
restingThresh: 2,
// debug: {
// renderFill: false
// },
gravity: {
y: 0
}
}
},
scene: [bootScene, playScene]
};
// create a new game, pass the configuration
let game = new Phaser.Game(config);
test.js:
function test(msg,x,y,texture){
console.log(msg)
this.matter.add.image(x,y,texture)
}
I have tried trying to put t.test(etc.) and adding the load script in preload. I tried looking up examples, but I couldn't find any.
Sorry if this is a really obvious fix or im just terrible
You just need to pass the current scene, as a parameter, to the test function, and you will can access the matter object and other properties / functions, from the scene.
function test(scene, msg, x, y, texture) {
console.log(msg);
scene.matter.add.image(x, y, texture);
}
And the function test would have to be called, with the "current scene" in the case it is this:
...
create() {
...
test(this, 'test', 1, 1, 'linus');
...
}
This example of the offical website: Example Script Loading, illustrates this fact indirect. Im that example the scene is not passed as paramter, but the canvas and the context are.
So following this example, passing the scene should solve your problem.
Side Note: In general, if there is no specific reason, to load scripts from inside of a phaser application (as shown above), I would load the scripts within the html-file or use a web-bundler like webpack or others. Not only for performance/minification reason.

Unexpected error when attempting to update chart data in Chart.js, in a Vue app

I am using Chart.js 3.5 and Vue 3.
I was successfully able to draw a chart, and I am trying to trigger a data change, inside a Vue method. Unfortunately, I encounter the following issue: "Uncaught TypeError: Cannot set property 'fullSize' of undefined".
Edit2: Added a missed }. Code should now be runnable
MyChart.vue:
<template>
<canvas id="chartEl" width="400" height="400" ref="chartEl"></canvas>
<button #click="addData">Update Chart</button>
</template>
<script>
import Chart from 'chart.js/auto';
export default {
name: "Raw",
data() {
return {
chart: null
}
},
methods: {
createChart() {
this.chart= new Chart(this.$refs["chartEl"], {
type: 'doughnut',
data: {
labels: ['VueJs', 'EmberJs', 'ReactJs', 'AngularJs'],
datasets: [
{
backgroundColor: [
'#41B883',
'#E46651',
'#00D8FF',
'#DD1B16'
],
data: [100, 20, 80, 20]
}
]
},
options: {
plugins: {}
}
})
},
addData() {
const data = this.chart.data;
if (data.datasets.length > 0) {
data.labels.push('data #' + (data.labels.length + 1));
for (var index = 0; index < data.datasets.length; ++index) {
data.datasets[index].data.push(123);
}
// Edit2: added missed }
this.chart.update(); } // this line seems to cause the error}
}
},
mounted () {
this.createChart()
},
}
</script>
Edit1: Adding the following to the options makes the chart update successfully, but the error is still present and the animation does not work. The chart flickers and displays the final (updated) state. Other animations, such as hiding/showing arcs do not seem to be afected
options: {
responsive: true,
}
Edit3: Adding "maintainAspectRatio:false" option seems to again stop chart from updating (the above mentioned error is still present)
By walking through the debugger, the following function from 'chart.esm.js' seems to be called successfully a few times, and then error out on last call:
beforeUpdate(chart, _args, options) {
const title = map.get(chart); // this returns null, which will cause the next call to error with the above mentioned exception.
layouts.configure(chart, title, options);
title.options = options;
},
//////////////////////
configure(chart, item, options) {
item.fullSize = options.fullSize;
item.position = options.position;
item.weight = options.weight;
},
This may be a stale post but I just spent several hours wrestling with what seems like the same problem. Perhaps this will help you and/or future people with this issue:
Before assigning the Chart object as an attribute of your Vue component, call Object.seal(...) on it.
Eg:
const chartObj = new Chart(...);
Object.seal(chartObj);
this.chart = chartObj;
This is what worked for me. Vue aggressively mutates attributes of objects under its purview to add reactivity, and as near as I can tell, this prevents the internals of Chart from recognising those objects to retrieve their configurations from its internal mapping when needed. Object.seal prevents this by barring the object from having any new attributes added to it. I'm counting on Chart having added all the attributes it needs at init time - if I notice any weird behaviour from this I'll update this post.
1 year later, Alan's answer helps me too, but my code failed when calling chart.destroy().
So I searched and found what seems to be the "vue way" of handling it: markRaw, here is an example using options API:
import { markRaw } from 'vue'
// ...
export default {
// ...
beforeUnmount () {
if (this.chart) {
this.chart.destroy()
}
},
methods: {
createChart() {
const chart = new Chart(this.$refs["chartEl"], {
// ... your chart data and options
})
this.chart = markRaw(chart)
},
addData() {
// ... your update
this.chart.update()
},
},
}

Using Javascript Variables in scss

It's going to be awhile that I'm trying to find a solution to use javascript variables has scss value.
Let me explain my issue.
I use VueJs/Vuetify and I've got two entry point for my theme.
The first one is a json file like that :
module.exports = {
primary: { base: '#4d7cff', dark: '#2756d8', light: '#96b0fb' },
secondary: { base: '#00bda5', dark: '#209284', light: '#cef1ec' },
content: { base: '#37467a', dark: '#242c47', light: '#c3cbe6' },
danger: { base: '#e43858', dark: '#d22545', light: '#E36d83' },
success: { base: '#00c28d', dark: '#199c79', light: '#0bebae' },
accent: '#f5f8fa',
gradient: 'linear-gradient(45deg, #00bda5, #4d7cff)'
}
This file is required and use by vuetify two create custom color values and works perfectly.
The second one is a simple scss file :
// Theme colors
$color-primary-base: #4d7cff;
$color-primary-dark: #2756d8;
$color-primary-light: #96b0fb;
$color-secondary-base: #4d7cff;
$color-secondary-dark: #209284;
$color-secondary-light: #cef1ec;
$color-content-base: #37467a;
$color-content-dark: #242c47;
$color-content-light: #c3cbe6;
$color-danger-base: #e43858;
$color-danger-dark: #d22545;
$color-danger-light: #ff8097;
$color-success-base: #00c28d;
$color-success-dark: #199c79;
$color-success-light: #14e1a9;
$color-accent: #f5f8fa;
My goal would be to connect the json file with the scss variables to have one entry point for the entire app.
Why do this ?
Vuetify offers a scss variable overload system to modify the style of the components.
the idea would be to control this overload from the javascript file
In addition to that, due to vuetify limits, there are certains points where I must to control the color in a responsive context (for example a white header on desktop and blue on mobile) and therefore am obliged to use scss variables.
I've find this article on medium who at first sight seems to answers my problem.
But when I try to test it I've got the following error :
in ./src/assets/styles/vuetify.scss
Module build failed (from ./node_modules/sass-loader/dist/cjs.js):
ValidationError: Invalid options object. Sass Loader has been initialized using an options object that does not match the API schema.
- options has an unknown property 'options'. These properties are valid:
object { implementation?, sassOptions?, prependData?, sourceMap?, webpackImporter? }
at validate (C:\Users\33770\Documents\Calimed\novalys-front\node_modules\schema-utils\dist\validate.js:96:11)
at Object.loader (C:\Users\33770\Documents\Calimed\novalys-front\node_modules\sass-loader\dist\index.js:36:28)
Vuetify.scss
#import './novalys/map.scss';
#import '~vuetify/src/styles/main.sass';
vue.config.js
const sass = require('node-sass')
const sassUtils = require('node-sass-utils')(sass)
const sassVars = require(__dirname + '/src/theme/index.js')
module.exports = {
css: {
loaderOptions: {
scss: {
prependData: `#import "#/assets/styles/novalys/map.scss";`,
options: {
functions: {
'get($keys)': function(keys) {
keys = keys.getValue().split('.')
let result = sassVars
let i
for (i = 0; i < keys.length; i++) {
result = result[keys[i]]
}
result = sassUtils.castToSass(result)
return result
}
}
}
}
}
},
transpileDependencies: ['vuetify']
}
Can someone here would help me to find a possible solution ?
I've heard about an inverse solution by exporting a scss variable like that
:export {
some-variable: 'some-value';
}
But my idea is to have the entry point in json not a scss file.
Thank you in advance !

Ignite UI export large dataset halts the page

The version I'm using is 15.2. Previously I have been having no problems downloading a small dataset into Excel. However, for the current page, the data set is slightly larger than usual (280 rows x 14 columns). Every time I click the export button the page will halt (no Excel is generated after waiting for a min+). Does anyone have similar experience like this before and how to work around it?
Here's a snippet of the export function
$('#exportButton')
.on({
click: function() {
var fileName = getExportFileNameForSingleDate("NAV_Comparison");
$.ig.GridExcelExporter.exportGrid($("#grid"),
{
fileName: fileName,
tableStyle: 'tableStyleLight13'
},
{
exportStarting: function(e, args) {
showExportingIndicator(args.grid, exportingIndicator);
},
success: function() {
hideExportingIndicator(exportingIndicator);
}
});
}
});
function showExportingIndicator(grid, exportingIndicator) {
exportingIndicator.css({
"width": grid.outerWidth(),
"height": grid.outerHeight()
})
.html('<span class="exporting-text">Processing...</span>');
exportingIndicator.addClass("exporting-indicator");
grid.append(exportingIndicator);
}
function hideExportingIndicator(exportingIndicator) {
exportingIndicator.remove();
}
Have you upgraded your product to a higher version ? Supporting hierarchical data exporting was introduced in 16.1 and this definitely slowed down exporting,though in latest versions this performance issue was handled and as you can see in this example (http://jsfiddle.net/8unab211/1/)exporting 2500 records x 12 columns seems pretty fine. I can have a further look if you specify the exact version used and provide a sample chunk of your data:
$.ig.GridExcelExporter.exportGrid($("#grid1"), {
fileName: "igGrid",
gridFeatureOptions: {
paging: "allRows",
},
});

c3.generate not throwing error

I'm using c3 + d3 + javascript to create a line chart in a webpage. I managed to create a code that was working fine locally, but when I uploaded it to my server, the code stopped working. I explain the problem below:
Problem: c3.generate is not throwing errors when uploaded to server
JSFiddle: http://jsfiddle.net/xq6wmyvp/10/
var chart;
function initialize(path) {
try {
c3.generate({
bindto: '#chart',
data: {
x: 'label',
url: path,
type: 'line',
},
axis: {
x: {
type: 'categories',
label: {
text: 'days',
},
},
y: {
label: {
text: 'yield',
},
tick: {
format: d3.format(".2%")
}
}
},
});
} catch (err) {
return false;
}
return true;
}
var path1 = 'https://gist.githubusercontent.com/SamMorrowDrums/f571240047c0344a4af8/raw/433eae455570b64edcdc7ece39416b468b612f49/test.csv';
alert(initialize('blabla'));
Code explanation: the code (in the fiddle) has a function that initializes a chart with a line graph using some data. The path to the data is given as a variable to that function (which is called 'initialize(path)'). This function uses c3.generate to create the graph. If the data is not available or does not exist, c3.generate throws an error (this works locally, but not when uploaded to a server - this is the problem) and the function (initialize) returns false. If the data exists, the graph is loaded and 'initialize' returns true.
Problem Restated: after uploading the code to a server, the function 'initialize(path)' only returns 'true', even if the data is not available/non-existent.
I don't know how to solve this. Can you help me?
Thanks for reading!
(Github link to problem: https://github.com/masayuki0812/c3/issues/960)
As I stated in my comment, under the hood c3 is using a d3.xhr to retrieve the data. This is an async call meaning that it's outside of your try block.
Possible workarounds include:
1.) fix it in the c3 source code At line 1903, you see the error is being dropped.
2.) create a global error handler
3.) don't use c3's url option. Issue your own d3 xhr request (handle the error the proper way there) and if successful, then call c3.generate with the columns option. This is the way I'd do it.
d3.csv("path/to/file.csv", function(error, json) {
if (error){
// handle error properly
return;
}
c3.generate({
...
});
});

Categories