Asynchronous Shield UI JavaScript Chart creation and data binding - javascript

After having tried a couple of ways to solve the issue, I decided to ask for some help. The thing is, that I provide information on a website, which users in most cases don’t look too much. On the other hand this information needs to be a click away if needed. So I am using a Shield UI JavaScript chart, that binds to remote data. What I need is to initialize the chart, but not to show the data. This needs to be postponed until (and if) the user clicks on the chart.
Is there a way to bind the data later (asynchronously). How can this be achieved?
Below is some code I worked on, for testing purposes it is local data.
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8" />
<link rel="stylesheet" type="text/css" href="../../../css/shieldchart.css" />
<script src="../../../../external/jquery-1.8.2.min.js" type="text/javascript">//</script>
<script src="../../../../external/jquery.mousewheel/jquery.mousewheel.js" type="text/javascript">//</script>
<script src="../../../../external/canvg-1.2/rgbcolor.js" type="text/javascript">//</script>
<script src="../../../../external/canvg-1.2/canvg.js" type="text/javascript">//</script>
<script src="../../../../external/globalize/globalize.js" type="text/javascript">//</script>
<script src="../../../../common/core.js" type="text/javascript">//</script>
<script src="../../../js/shieldchart.js" type="text/javascript">//</script>
</head>
<body>
<div id="container" style="width: 600px; height: 400px; margin: auto;"></div>
<script type="text/javascript">
$(document).ready(function () {
var Information= [12,22,22,12,32,44,34 ];
$("#container").shieldChart({
events: {
seriesClick: function pointSelectHandler(args) {
var containterproducts = $("#container").swidget();
containterproducts.destroy();
$("#container").shieldChart({
exportOptions:
{
image: false,
print: false
},
primaryHeader: {
text: "Electricity prices"
},
dataSeries: [
{
seriesType: 'pie',
collectionAlias: "User Information",
data: Information
},
]
});
}
},
exportOptions:
{
image: false,
print: false
},
primaryHeader: {
text: "Click to show data"
},
});
});

You are on a right way to solve the problem. You initially create a chart that contains no data and eventually bind it to the data source.
However you may not use the seriesClick event, since you don’t have any series that the user can click on.
If you want to use that event, than you need to add for instance a single value, let’s say 1, so that the user is able to click on the pie:
dataSeries: [
{
seriesType: 'pie',
collectionAlias: "Logins",
data: [1]
},
]
or alternatively, you can have your code and only change the event used:
click: function pointSelectHandler(args) {}
In this case you will show the data when the user clicks on the chart and won’t be in need of any series.
This is the more comfortable strategy, because with the pie chart type it is easy to visualize a sample data series. But if you are using line type chart it will be more complicated for the user to get to know that he needs to click on a data series to get the actual data.

Related

How to save a csv file uploaded from my machine into a data object in javascript?

I'm building a page that can display a chart of sensor data from a csv file. The user should be able to click on a button to choose a desired csv file from his machine to be displayed on a chart. I'm using the Highcharts library for that. The chart works as desired, but I can only input the csv file in code. When I upload a file and update nothing happens. So how can I make "data.csv" dynamic? My idea was to somehow save it into a global data object, that can then be passed into ajax url. I don't know how to implement this, since this is my very first javascript project.
<!DOCTYPE html> <!-- Write your comments here -->
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://code.jquery.com/jquery-3.5.1.min.js"
integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script src="https://code.highcharts.com/highcharts.js"></script> <!-- library include-->
<script src="https://code.highcharts.com/modules/data.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<script src="https://code.highcharts.com/highcharts-more.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/4.1.2/papaparse.js"></script>
<title>Airmeter</title>
</head>
<body>
<div id="container"></div>
<form id='form'>
<input type="file" accept=".csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel" id="input" />
<button type='submit'>
update the chart
</button>
</form>
<script>
$.ajax({
type: "GET",
url: "data.csv",
success: function (data) {
setTitle(data)
}
});
function setTitle(raw_data){
let newTitle;
let chart = Highcharts.chart('container', {
chart: {
zoomType: 'xy',
events: {
load: function() {
this.update({
title: {
text: 'Airmeter: '+ newTitle
}
})
}
}
},
xAxis:{
title:{
text: 'Zeit'
}
},
yAxis:{
title:{
text: 'CO2 in ppm'
}
} ,
exporting:{
enabled: true
},
title: {
text: null
},
credits:{
enabled: false
},
data: {
csv: raw_data,
parsed(e) {
newTitle=e[0][1] //set the first column as title of the chart
e.shift()
}
}
});
}
</script>
</body>
</html>
I would really appreciate help. Thanks for your time and have nice day!
If the CSV will always be on your local machine rather than a server, you don't really need to be using an AJAX call and you could use the FileAPI and a CSV parser to pass the data to your setTitle function.
But to help with your approach, try doing these changes to your code:
Add an onChange event to your input, so whenever a file is selected, the javascript code can 'react' to it.
Wrap your AJAX call in the 'change' event handler.
Pass the selected file name to your AJAX request's URL.
In terms of code changes (untested):
<script>
// Add an event listener, so when a file is selected, the graph is drawn again
document.getElementById("input").addEventListener("change", drawGraph, false);
// Wrap your current AJAX call in the event handler
function drawGraph() {
// Obtain the name of the file selected by the user in the <input>
var fileName = document.getElementById('input').files[0].name;
$.ajax({
type: "GET",
url: fileName, // use this name to fetch the selected file
success: function (data) {
setTitle(data)
}
});
}
// Leave the rest of the script block as it is
// ...
</script>

using Highstock and Highchart-Gantt on same page

I am trying to use the Highcharts set of javascript libraries to create a page that displays both a stock prices chart and a gantt chart (using the Highstocks and Highcharts Gantt libraries)
I do not have problems creating and displaying either of these plots independently on separate pages.
However, I cannot get the two libraries to work together in order to display these two plots on the same webpage.
I would appreciate any help i can get on how to get these two libraries to work together.
Attempt 1. If I import the highstock script first
<script src="https://code.highcharts.com/stock/highstock.js"></script>
<script src="https://code.highcharts.com/gantt/highcharts-gantt.js"></script>
then the following happens:
the prices plot will display but the gantt plot does not.
It throws two error messages in the console:
Uncaught Error: Highcharts error #16: www.highcharts.com/errors/16
at m (highstock.src.js:463)
at Object.d.error (highstock.src.js:474)
at highcharts-gantt.src.js:21
at highcharts-gantt.src.js:9
and
Uncaught TypeError: Highcharts.ganttChart is not a function
at myExample.html:60
Attempt 2. If I import the gantt script first
<script src="https://code.highcharts.com/gantt/highcharts-gantt.js"></script>
<script src="https://code.highcharts.com/stock/highstock.js"></script>
then the following happens:
the gantt plot will display but the prices plot does not.
It throws two error messages in the console:
Uncaught Error: Highcharts error #16: www.highcharts.com/errors/16
at d (highcharts-gantt.src.js:463)
at Object.c.error (highcharts-gantt.src.js:474)
at highstock.src.js:21
at highstock.src.js:9 ```
and
Uncaught TypeError: Highcharts.stockChart is not a function
at myExample.html:28
Example Code
A minimum viable code for demonstrating the problem i am running into is below:
<html>
<head>
<script src="https://code.highcharts.com/stock/highstock.js"></script>
<script src="https://code.highcharts.com/gantt/highcharts-gantt.js"></script>
</head>
<body>
<!-- ================================================================== -->
<!-- PRICES PLOT -->
<!-- ================================================================== -->
<div id="pricesChart" style="height: 500px; min-width: 310px"></div>
<script type="text/javascript">
var prices =
[[Date.parse("2019-06-01 00:00:00"), 0.081558],
[Date.parse("2019-06-02 00:00:00"), 0.081728],
[Date.parse("2019-06-03 00:00:00"), 0.081624],
[Date.parse("2019-06-04 00:00:00"), 0.08164500000000001]
];
var lineplotOptions = {
xAxis: { type: 'datetime' },
series: [{
type: "line",
data: prices,
yAxis: 0,
}],
};
Highcharts.stockChart('pricesChart', lineplotOptions);
</script>
<!-- ================================================================== -->
<!-- GANT CHART -->
<!-- ================================================================== -->
<div id="container"></div>
<script type="text/javascript">
var tasks =
[{
start: Date.parse("2019-06-01 06:00:00"),
end: Date.parse("2019-06-01 20:30:00"),
name: 'task1'
}, {
start: Date.parse("2019-06-01 09:20:00"),
end: Date.parse("2019-06-03 02:00:00"),
name: 'task2'
}, {
start: Date.parse("2019-06-02 11:00:00"),
end: Date.parse("2019-06-03 21:10:00"),
name: 'task1'
}];
var gant_options = {
yAxis: { uniqueNames: true },
scrollbar: {enabled: true },
series: [{
name: 'Project 1',
data: tasks
}]
}
var mychart = Highcharts.ganttChart('container', gant_options);
</script>
</body>
</html>
Similar questions on stackoverflow
The following are similar questions on stack overflow, but which don't quite deal with my specific case.
Using highcharts & highstock together on same page
use highchart and highstock on the same page
These two deal with highcharts and highstock libraries on the same page.
Highstock library extends on the functionality of highcharts, so there is no need to also import highcharts.
This does not help my case because the functionality i need is not included in either highstock or highcharts-gantt on their own.
You can load highstock and highcharts-gantt separately like that:
<script src="https://code.highcharts.com/stock/highstock.js"></script>
<script>
var Highstock = window.Highcharts;
window.Highcharts = null;
</script>
<script src="https://code.highcharts.com/gantt/highcharts-gantt.js"></script>
initialization:
Highstock.stockChart('container1', {
series: [{
data: []
}]
});
Highcharts.ganttChart('container2', {
series: [{
data: []
}]
});
Demo:
https://jsfiddle.net/BlackLabel/Lxnjwsb9/1/

Fullcalendar : minTime wrongly calculate fc-not-start

I am using the Fullcalendar library, scheduler module.
I use minTime properties and set it to: '06:00:00' inside of view definition (so that "day is not start with midnight").
But when I that, the calendar elements that starts before 6h has a class fc-not-start even when they are in the middle of the calendar...
How to handle this?
EDIT :
Some additional information:
Fullcalendar version: v3.9.0
fc-not-start : This class should have calendar (scheduled) elements that are not started in this view. (The start is invisible). This is needed because, if element has some rounded corners, border,... it should't have on the left side if start is not visible. (Or if you want to display icon, that you are not looking at full element)
Example:
Inside the red square, this is a right use of fc-not-start
This is the wrong use of the fc-not-start
The fc-not-start should calculate itself inside fullcalendar library and it is working, until I add the parameter minTime in view.
EDIT 2:
I create minimal code to see the problem
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Demo</title>
<link rel='stylesheet' href='css/fullcalendar.css' />
<link rel='stylesheet' href='css/scheduler.css' />
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<link rel='stylesheet' href='css/style.css' />
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div id='calendar'></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.0.0/jquery.min.js"></script>
<script src='js/moment.js'></script>
<script src='js/fullcalendar.js'></script>
<script src='js/scheduler.js'></script>
<script src='js/my_script.js'></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
</body>
</html>
JS
var resources = [
{
id: 'A',
title: 'A',
sortOrder: 1
},
{
id: 'B',
title: 'B',
sortOrder:2
},
{
id: 'C',
title: 'C',
sortOrder:3
}
];
$('#calendar').fullCalendar({
// height: 550,
// eventColor: '#428bca',
schedulerLicenseKey: 'CC-Attribution-NonCommercial-NoDerivatives',
defaultView: 'timelineFourDays',
views: {
timelineFourDays: {
type: 'timeline',
minTime: '07:00:00',
duration: { days: 4 }
},
},
resources: resourcesFunc,
nowIndicator: true,
events: [
{
id: '1',
resourceId: 'A',
title: 'Meeting',
start: '2019-07-13T00:20:00',
end: '2019-07-14T02:20:00',
},
{
id: '2',
resourceId: 'A',
title: 'Meeting2',
start: '2019-07-13T00:20:00',
end: '2019-07-14T02:20:00',
}
],
displayEventTime: true,
});
function resourcesFunc(callback) {
callback(resources);
}
The < should be only if the element is not whole visible on screen. In this case this class is wrongly calculated...
https://jsfiddle.net/Ly9rsoc1/2/
You said
"The < should be only if the element is not whole visible on screen"
However: Your events start before the specified minTime value. This means that the start point of the event can never be visible on your calendar. Therefore the < icon is displayed.
I think you have misunderstood the nature of this functionality. It's not about whether the start of the HTML element is visible, it's about whether the start of the event (which is represented by that HTML element) is visible. And since you removed some of the times covered by that event from your display, then it displays the icon so that this fact is clear to the user.
In conclusion: The calendar is behaving exactly as it should. There is no bug here.
As an aside, I would point out that if you routinely have events which cover these times of day, then in my opinion it's not very logical or very user-friendly to make those times invisible, because it hides what might be useful information. But if these particular events are an anomaly, and most of your events are after 7am then you might just have to tolerate these ones as an unusual case.

Uncaught ReferenceError: require is not defined with Dojo API

I have seen multiple incarnations of this error, but not seen an answer directly related to using the Dojo API/CDN. I am just going through a quick Dojo charting tutorial to figure out how to correctly apply a pie chart. I was using the simple instructions to set up a web page I could use to test from my local (see below). Everytime I launch the .html file, I get the error - Uncaught ReferenceError: require is not defined. All previous answers point to the src being faulty, whether its a cdn, api, or file path. I have tried multiple cdn's and configurations, including src="//ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo/dojo.js"and
<script data-dojo-config="async: 1"
src="//ajax.googleapis.com/ajax/libs/dojo/1.10.4/dojo/dojo.js"></script>`,
yet I still get the same error (These are straight from the documentation). Any suggestions as to what is causing this error and how to resolve it to test my simple pie chart?
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Tutorial: Pie Chart!</title>
<script> src="//ajax.googleapis.com/ajax/libs/dojo/1.13.0/dojo/dojo.js"></script>
</head>
<body>
<script>
require([
'dojo/dom',
'dojo/dom-construct',
'dojox/charting/Chart',
'dojox/charting/themes/Claro',
'dojox/charting/PiePlot'
], function (dom, domConstruct, Chart, theme, PiePlot) {
var pieChart = new Chart("chartNode");
// Set the theme
pieChart.setTheme(theme);
// Add the only/default plot
pieChart.addPlot("default", {
type: PiePlot, // our plot2d/Pie module reference as type value
radius: 200,
fontColor: "black",
labelOffset: -20
});
// Add the series of data
pieChart.addSeries("January",chartData);
// Render the chart!
pieChart.render();
});
</script>
<div id="chartNode" style="width: 550px; height: 550px;"></div>
</body>
</html>
The first thing that there is a type error in your script tag line 6 ,
closed tag script and src attrib outside the script tag , that why you have the error reuire is not ...
Also after correcting those you'ill still have some errors ,
so you need to fix an import
The 'dojox/charting/PiePlot' should be replaced by 'dojox/charting/plot2d/Pie'
and you need to declare your chartData here ,
If you need a file version see this GIST
Otherwise see below working snippet :
require([
'dojo/dom',
'dojo/dom-construct',
'dojox/charting/Chart',
'dojox/charting/themes/Claro',
'dojox/charting/plot2d/Pie'
], function(dom, domConstruct, Chart, theme, PiePlot) {
chartData = [
{ y: 389, text: "data1 " },
{ y: 125, text: "data 2" },
{ y: 285, text: "data 3" },
{ y: 193, text: "data 4" },
{ y: 21, text: "No data" }
];
var pieChart = new Chart("chartNode");
// Set the theme
pieChart.setTheme(theme);
// Add the only/default plot
pieChart.addPlot("default", {
type: PiePlot, // our plot2d/Pie module reference as type value
radius: 200,
fontColor: "black",
labelOffset: -20
});
// Add the series of data
pieChart.addSeries("January", chartData);
// Render the chart!
pieChart.render();
});
<script src="//ajax.googleapis.com/ajax/libs/dojo/1.10.0/dojo/dojo.js"></script>
<div id="chartNode" style="width: 550px; height: 550px;"></div>

Google Analytic Embed API chart: Responsive

How would I make this Google Analytic Embed API chart responsive? I noticed that the demo on this page is reponsive: https://ga-dev-tools.appspot.com/embed-api/basic-dashboard/
I have also seen various ways of doing this with Google Charts here
https://code.google.com/p/google-visualization-api-issues/issues/detail?id=1056
<!doctype html>
<html lang="en">
<head>
<title>Google Charts</title>
<script>
(function(w,d,s,g,js,fs){
g=w.gapi||(w.gapi={});g.analytics={q:[],ready:function(f){this.q.push(f);}};
js=d.createElement(s);fs=d.getElementsByTagName(s)[0];
js.src='https://apis.google.com/js/platform.js';
fs.parentNode.insertBefore(js,fs);js.onload=function(){g.load('analytics');};
}(window,document,'script'));
</script>
<script>
gapi.analytics.ready(function() {
var ACCESS_TOKEN = 'XXX'; // obtained from your service account
gapi.analytics.auth.authorize({
serverAuth: {
access_token: ACCESS_TOKEN
}
});
var linechart = new gapi.analytics.googleCharts.DataChart({
query: {
ids: 'ga:XXXXXX',
metrics: 'ga:users',
dimensions: 'ga:date',
'start-date': '30daysAgo',
'end-date': 'yesterday'
},
chart: {
type: 'LINE',
container: 'line-chart',
options: {
width: '100%',
title: 'Test.com: Visitors over the past 30 days.',
fontSize: 12
}
}
});
linechart.on('success', function(response) {
// response.chart : the Google Chart instance.
// response.data : the Google Chart data object.
});
linechart.execute();
});
</script>
</head>
<body>
<div>
<div id="embed-api-auth-container"></div>
<div id="line-chart" style='width:100%;height:300px;'></div>
</div>
</body>
</html>
I answered this over here
(Google Embed API) How to change chart-table-style width
Basically you just add an option element and assign width of x% within the charts option element
I just noticed the same issue, setting:
options: {
width: '100%'
}
doesn't work when document width changes (only 'TABLE' chart is responsive 'out of the box').
As workaround, you need to trigger a chart redraw on window resize:
window.addEventListener('resize', function() {
linechart.execute();
});
Sidenotes:
linked Google page doesn't seems to use this or whatelse workarounds to have the chart responsive but the behavior is the same;
if you have animations enabled in your chart those animations might be played multiple times on window resize;
I was using google analytics API and I had the same issue but it worked for me by adding
options:{width:'100%'}
chart: {
type: 'LINE',
container: 'timeline',
options: {width: '100%'}
}

Categories

Resources