why Graph is not showing until i minimize window. (using chart.js ) - javascript

I'm using chart.js for first time and I'm facing problem in drawing graph. When I run this code, Graph axis are shown only but bars are not shown until I minimize or change browser window size. This is happening every time. Maybe this has to do with responsiveness. Any help about what I'm doing wrong here. I'm using visual studio and chrome for rendering graph.
let labels=[]
let duration=[]
let file="assets/duration.csv";
d3.csv(file).then(
function (loaddata) {
for (let i = 0; i < loaddata.length; i++) {
//console.log(loaddata.hours)
if (loaddata[i].hours != 0)
{
duration.push(loaddata[i].hours)
labels.push(loaddata[i].Trend)
}
}
//console.log(labels)
//console.log(duration)
}
);
let options={
type: 'bar',
responsive: true,
title: {
display:true,
text:'Duration of Trending Tweets'
},
data: {
labels:labels,
datasets:[{
data: duration,
label: 'Hours',
backgroundColor:["#3e95cd"]
}]
}
};
let chart=new Chart(document.getElementById('canvas'),options);
<!DOCTYPE html>
<html lang="en">
<head>
<script src="chart.min.js"></script>
<script src ="https://cdn.jsdelivr.net/npm/chart.js#3.7.1/dist/chart.min.js">
</script>
<script src="http://d3js.org/d3.v5.min.js" charset="utf-8"></script>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My first website</title>
</head>
<body>
<h1>Hello world</h1>
<div>
<canvas id="canvas" style="position: relative; height:40vh; width:80vw">
</canvas>
</div>
<script src="index.js">
</script>
</body>
</html>

The problem is that you create the chart before the CSV data is loaded. Be aware that the d3.csv request is processed asynchronously.
This can be solved by creating the chart only once the CSV data is fully loaded (at the end and inside of d3.csv(file).then( ... ).
An alternative approach is described in this answer.

Related

I dont know whats wrong with this simple javascript code, I have checked this over and over again but does not work

Simple image expanding on mouseover and opposite on mouseout, I checked the code over and over, putting alert messages at each line to see if its working, alert message work all the way to the end but there is no effect on the image. I am so confused, I dunno whats wrong.
var side = 200;
var a = 20;
var t = 0;
function expand() {
console.log("expand is ok");
clearInterval(t);
t = setInterval(grow, 20);
}
function grow() {
console.log("Entered grow");
if (side < 300) {
console.log("entered if loop");
side = side + a;
document.getElementById("new").style.width = side;
console.log("After statement")
} else
clearInterval(t);
console.log("clear")
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Zoom in Zoom out</title>
</head>
<body>
<img src="../images/women.jpg" id="new" alt="Women" onmouseover="expand()" width=2 00px>
</body>
</html>
To expand on my comment:
The issue is you're trying to assign a raw number such as 200 to the width CSS property.
If you look at CSS, you'd spell "200 pixels" as
foo {
width: 200px;
}
so similarly you'll need to endow the dynamic manipulation with an unit (pixels here):
foo.style.width = `${width}px`;

Chart.js not drawing on mobile (safari/chrome) fine on desktop

I've got a piechart that works perfectly fine on desktop. It retrieves data from an AJAX request and stores the data/json it gets. Selected data is then pushed into the chart. I am using Thymeleaf & Spring in but thats not relevant here I believe.
Everything is rendered fine on my page when I access it through Safari or chrome on mobile, however the graph is not present.
I've tried changing responsive true/false, maintaingAspectRatio false/true, playing with other options provided in the chart.js documentation. Changed the viewport, set my width on the container of the canvas rather than the canvas it self and a whole bunch of other stuff.
Could it be due to the load order? i.e the page is loaded before it can actually get the information from the request? However, that would mean that it shouldn't be working on desktop either.
Here is some code
myGraph.js
$(document).ready(function () {
var id = $.url(2);
$.ajax({
url: "hosturl/a/b/" + id + "/c/d",
type: "GET",
dataType: "json",
success: function (data) {
console.log(data);
var count = [];
var days = [];
for (var i in data) {
days.push(data[i][1]);
count.push(data[i][0]);
}
var chartdata = {
labels: days,
datasets: [
{
label: "By day",
backgroundColor: "#4dc3ff",
borderWidth: 2,
hoverBackgroundColor: "#009",
hoverBorderColor: "#099",
hoverBorderWidth: 5,
data: count
}
]
};
var ctx = $("#daysGraph");
var pieChart = new Chart(ctx, {
type: 'pie',
data: chartdata,
options: {
responsive: true,
legend: {
display: true,
position: 'right',
labels: {
fontColor: "#000"
}
}
}
});
},
error: function (data) {
}
});
graph.html (most of the other html is cut out out, but this on its own doesn't work)
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-
scale=1,maximum-scale=7"/>
<title>Hmm</title>
<script type="text/javascript" src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css"/>
<script src="../../javascript/Chart.min.js" th:href="#{/Chart.min.js}"/>
<script src="../../javascript/js-url-2.5.0/url.js" th:href="#{/url.js}" ></script >
<link rel="stylesheet" href="../static/css/graph.css" th:href="#{/css/graph.css}"/>
<script src="../../javascript/myGraph.js" th:href="#{/myGraph.js}" />
</head>
<body>
<div class="chart-container">
<canvas id="daysGraph" ></canvas>
</div>
</body>
</html>
graph.css
.chart-container {
position: relative;
margin: auto;
height: 80vh;
width: 80vw;
}
On the live server it looks like this
Any advice is welcome
Turned out there was something wrong with the api-route on mobile vs dektop relating to localhost. Therefore my data wasn't being fetched from the api and thus wouldn't populate the chart which is why it is not displaying on mobile. In other words, I was looking in the wrong places for an answer.
I've had similar problems myself, I resolved my issue by playing around with the borderWidth in order to get it working across all devices. Try changing it several times to see if it has any impact at all.

execCommand copy async alternative for Firefox

document.execCommand('copy') can be used inside the resolve function of a Promise except for Firefox.
Every modern browsers like Chrome, Opera, and even Safari allow async copy up to 1 second.
I want to improve the user experience and copy data following a calculation in the clipboard.
Is there a solution to copy the result of a Promise with Firefox in one click?
Here a snippet working with Chrome
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Test</title>
</head>
<body>
<button onclick="copy(genPwd)">copy</button>
<script>
function genPwd() {
return new Promise(function(resolve) {
resolve('toto')
})
}
function copy(p) {
p().then(function(result) {
console.log('create fake text area');
var fakeTextArea = document.createElement('textarea');
fakeTextArea.setAttribute('readonly', '');
fakeTextArea.value = result;
document.body.appendChild(fakeTextArea);
fakeTextArea.select();
document.execCommand('copy');
});
}
</script>
</body>
</html>

HTML scripting not loading JavaScript file

I'm trying to display piechart in UIWebview of my iOS xcode project, for that I'm using jqplot with HTML, CSS and JavaScript, the issue I face is JavaScript file "devicepiechart.js" is loading from the html.
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" type="text/css" href="jquery.jqplot.css" />
<script>
function load()
{
alert("I am an loading scripts!");
}
</script>
<script src="devicepiechart.js"></script>
</head>
<body onload= "load()">
</body>
</html>
The load() function alert is shown properly without any problem. I could detect that my .js file is not loading as I have the alert("string"); function in my .js file too for debugging.
UPDATED devicepiechart.js, and I hope the external .js file may not have any error, because I have the source from this http://www.jqplot.com/tests/pie-donut-charts.php
$(document).ready(function()
{
alert("good");
var data = [
['Heavy Industry', 12],['Retail', 9], ['Light Industry', 14],
['Out of home', 16],['Commuting', 7], ['Orientation', 9]
];
var plot1 = jQuery.jqplot ('chart1', [data],
{
seriesDefaults: {
// Make this a pie chart.
renderer: jQuery.jqplot.PieRenderer,
rendererOptions: {
// Put data labels on the pie slices.
// By default, labels show the percentage of the slice.
showDataLabels: true
}
},
legend: { show:true, location: 'e' }
}
);
});
Include jquery before the other js loads
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
Just load all your .js files into "copy bundle resources" of project Targets "bulid phases" , now the piechart is running successfully in ios simulator.

Internet Explorer 8 Messing Up My Bulletgraphs

I've created HTML and JavaScript files to display bulletgraphs, using the 'canvas' HTML5 tag. I've tried it in Chrome and it works nicely and changes width along with the size of the browser. I have to have this working in IE8, too, so I've used Excanvas, which is working in all except one way: when I resize the browser I get remnants of the valueIndicator. This only happens on IE8.
I've tried looking round for information on redrawing the canvas but I don't think this is the issue. Can anyone see where I'm going wrong, please?
EDIT
I'm keeping the complete code at the bottom, however, following advice I've cut my code down somewhat.
In IE8 it looks like this:
In Chrome it looks like this:
When I refresh the IE8 page it looks OK again.
Cut-down Bulletgraph.html:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Bulletgraph</title>
<!--[if IE]><script src="excanvas.js"></script><![endif]-->
</head>
<body>
<canvas id="graph1"></canvas>
<script src="Scripts.js"></script>
<script>
drawGraphs();
window.onresize=function() { drawGraphs() };
function drawGraphs() {
drawBulletGraph(getScreenWidth(),300,1000,350,"graph1");
}
</script>
</body>
</html>
Complete code:
Cut-down Scripts.js:
function drawBulletGraph (cwidth, left, right, loValue, id) {
var canvas=document.getElementById(id);
var cheight=30;
var multiplier=cwidth/(right-left);
canvas.width=cwidth;
canvas.height=cheight;
var valueIndicator=canvas.getContext("2d");
valueIndicator.lineWidth="1";
valueIndicator.moveTo((loValue-left)*multiplier,0);
valueIndicator.lineTo((loValue-left)*multiplier,cheight);
valueIndicator.fill();
valueIndicator.stroke();
}
function getScreenWidth () {
return (window.innerWidth || document.documentElement.clientWidth)/7;
}
Bulletgraph.html:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Bulletgraph</title>
<!--[if IE]><script src="excanvas.js"></script><![endif]-->
</head>
<body>
<canvas id="graph1"></canvas><br>
<canvas id="graph2"></canvas>
<script src="Scripts.js"></script>
<script>
drawGraphs();
window.onresize=function() { drawGraphs() };
function drawGraphs() {
drawBulletGraph(bgWidth(getScreenWidth()),300,400,450,600,700,1000,800,350,850,"graph1");
drawBulletGraph(bgWidth(getScreenWidth()),250,450,500,650,700,1200,600,350,850,"graph2");
}
</script>
</body>
</html>
Scripts.js:
function drawBulletGraph (cwidth, left, loRed, loAmber, hiAmber, hiRed, right, value, loValue, hiValue, id) {
var canvas=document.getElementById(id);
var cheight=16;
var colour="#008000";
if (value <= loRed || value >= hiRed)
{
colour="#FF0000";
}
else if (value <= loAmber || value >= hiAmber)
{
colour="#FFA500";
}
var multiplier=cwidth/(right-left);
canvas.width=cwidth;
canvas.height=cheight;
var red=canvas.getContext("2d");
red.fillStyle="#F4C3C6";
red.fillRect(0,0,cwidth,cheight);
var amber=canvas.getContext("2d");
amber.fillStyle="#F4F6C6";
amber.fillRect((loRed-left)*multiplier,0,(hiRed-loRed)*multiplier,cheight);
var green=canvas.getContext("2d");
green.fillStyle="#CCE5CC";
green.fillRect((loAmber-left)*multiplier,0,(hiAmber-loAmber)*multiplier,cheight);
var valueIndicator=canvas.getContext("2d");
valueIndicator.fillStyle=colour;
valueIndicator.strokeStyle=colour;
valueIndicator.lineWidth="2";
valueIndicator.moveTo((loValue-left)*multiplier,0);
valueIndicator.lineTo((loValue-left)*multiplier,cheight);
valueIndicator.moveTo((loValue-left)*multiplier,cheight/2);
valueIndicator.lineTo((hiValue-left)*multiplier,cheight/2);
valueIndicator.moveTo((hiValue-left)*multiplier,0);
valueIndicator.lineTo((hiValue-left)*multiplier,cheight);
valueIndicator.moveTo(((value-left)*multiplier)-(cheight/2),cheight/2);
valueIndicator.stroke();
valueIndicator.lineWidth="1";
valueIndicator.lineTo((value-left)*multiplier,cheight);
valueIndicator.lineTo(((value-left)*multiplier)+(cheight/2),cheight/2);
valueIndicator.lineTo((value-left)*multiplier,0);
valueIndicator.lineTo(((value-left)*multiplier)-(cheight/2),cheight/2);
valueIndicator.fill();
valueIndicator.stroke();
}
function getScreenWidth () {
return window.innerWidth || document.documentElement.clientWidth;
}
function bgWidth (screenWidth) {
var graphWidth=screenWidth/7;
if (graphWidth<70) {graphWidth=70;}
if (graphWidth>260) {graphWidth=260;}
return graphWidth;
}
I've managed to get a solution. It feels like a bit of a hack but it does the trick. Basically it involves drawing a white line round the canvas and filling it each time it's drawn again. The following code goes between the var valueIndicator=canvas.getContext("2d"); and the valueIndicator.lineWidth="1"; lines:
valueIndicator.fillStyle="#FFFFFF";
valueIndicator.strokeStyle="#FFFFFF";
valueIndicator.moveTo(0,0);
valueIndicator.beginPath();
valueIndicator.lineTo(0,cheight);
valueIndicator.lineTo(cwidth,cheight);
valueIndicator.lineTo(cwidth,0);
valueIndicator.closePath();
valueIndicator.fill();
valueIndicator.stroke();
valueIndicator.strokeStyle="#000000";
I've tried it in the full code and it works. If anyone has a more elegant solution, and I'm sure there must be many, I would still love to see them.

Categories

Resources