I have an old web project that uses prototype.js and I'm trying to add charting to it using C3.
Unfortunately there's an error since prototype seems to add a bunch of methods to arrays and this specific method in c3.js checkValueInTargets uses Object.keys which grabs all the random methods in the array and then throws an error.
Is there a way to "hide" my charting code from prototype or a way to use the default JS arrays?
I can't remove or upgrade prototype unfortunately.
Thanks
sample project:
var chart = c3.generate({
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
['data2', 130, 100, 140, 200, 150, 50]
],
type: 'bar'
},
bar: {
width: {
ratio: 0.5 // this makes bar width 50% of length between ticks
}
// or
//width: 100 // this makes bar width 100px
}
});
http://jsfiddle.net/Yq3DW/269/
One easy way to fix it would be to move the prototype script loading to after c3.js chart initialization call.
...
<link href="lib/c3.js/c3.css" rel="stylesheet" />
</head>
<body>
...
<div id="chart"></div>
...
<script src="lib/d3/d3.js" charset="utf-8"></script>
<script src="lib/c3.js/c3.js"></script>
<script>
var chart = c3.generate({
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
['data2', 130, 100, 140, 200, 150, 50]
],
type: 'bar'
},
bar: {
width: {
ratio: 0.5 // this makes bar width 50% of length between ticks
}
// or
//width: 100 // this makes bar width 100px
}
});
</script>
<script src="lib/prototype/prototype.js"></script>
<!-- prototype code --->
</body>
If this is not possible, you could have a script block to store a reference to the native Object.keys and swap it out and back again when calling the C3 code, like so
<!DOCTYPE html>
<html lang="en">
<head>
<title>C3</title>
<meta charset="utf-8" />
<script>
var originalKeys = Object.keys;
</script>
<script src="lib/prototype/prototype.js"></script>
</head>
<body>
<div id="chart"></div>
<script src="lib/d3/d3.js" charset="utf-8"></script>
<script src="lib/c3.js/c3.js"></script>
<link href="lib/c3.js/c3.css" rel="stylesheet" />
<script>
var prototypeKeys = Object.keys;
Object.keys = originalKeys;
var chart = c3.generate({
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
['data2', 130, 100, 140, 200, 150, 50]
],
type: 'bar'
},
bar: {
width: {
ratio: 0.5 // this makes bar width 50% of length between ticks
}
// or
//width: 100 // this makes bar width 100px
}
});
Object.keys = prototypeKeys;
</script>
</body>
</html>
Luckily tooltips don't cause any problems
Fiddle - http://jsfiddle.net/td433xt1/
Related
I created a chart with Billboard.js (a chart library based on d3 v4+).
My aim was to make the lines look dashed so I used this documentation for it.
Basically, I added this code:
const regions = {}
for(const item of baselineTitle) {
regions[item]=[];
regions[item].push({"style" : "dashed"});
}
inside bb.generate:
var chart = bb.generate({
"data": {
"type": "spline",
"x": "x",
"columns": columns,
"regions": regions
},
...
When the lines are not dashed everything it's fine. I have no line on the chart for null values.
When it is dashed, it has a line on zero for all null values.
This is how my chart looks like, I put yellow color where it shouldn't be a line because the values are null for that part.
The array containing the values for that line is this one:
0:"char id"
1:null
2:null
3:null
4:2230.181884765625
5:2230.181884765625
6:2230.181884765625
7:2230.181884765625
8:2230.181884765625
9:2230.181884765625
10:2230.181884765625
11:2230.181884765625
12:2230.181884765625
13:2230.181884765625
14:2230.181884765625
15:2230.181884765625
16:4568.82470703125
17:4870.001953125
18:4671.97607421875
19:4767.93603515625
20:4729.97607421875
21:4721.1591796875
22:4799.16357421875
23:4864.5068359375
24:3512.424072265625
25:2924.76513671875
26:3047.808837890625
27:3052.245361328125
28:3045.63427734375
29:2930.223388671875
30:2410.9541015625
31:2116.904052734375
32:2064.01806640625
33:2159.795654296875
34:2232.72412109375
35:2669.738037109375
36:3420.1669921875
37:4515.5537109375
38:4703.1435546875
39:4993.89501953125
40:5207.1259765625
41:5056.1904296875
42:5222.80517578125
43:5509.8447265625
44:5453.8798828125
45:5206.78466796875
46:5155.16748046875
47:5082.36083984375
48:4002.560302734375
49:3587.09716796875
50:3569.875732421875
51:3328.478515625
52:3167.501953125
53:2847.85009765625
54:2208.728759765625
55:2152.306396484375
56:2085.06640625
57:2145.009521484375
58:2170.032958984375
59:2666.60107421875
60:3379.564208984375
61:4388.9384765625
62:4549.611328125
63:5117.0029296875
64:5279.7353515625
65:5314.0751953125
66:5404.16552734375
67:5757.20068359375
68:5631.9619140625
69:5716.732421875
70:5763.24560546875
71:5598.005859375
72:null
73:null
74:null
75:null
76:null
77:null
78:null
79:null
80:null
81:null
82:null
83:null
84:null
85:null
86:null
87:null
88:null
89:null
90:null
91:null
92:null
93:null
94:null
95:null
96:null
97:null
98:null
99:null
Do you know what's the problem here?
If you don't need to set a specific region of the line to be dashed, with the css stroke-dasharrayattribute will be more easier to implement that.
https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray
Check out the below snippet.
bb.generate({
data: {
columns: [
["data1", 100, 200, 1000, 900, 500],
["data2", 20, 40, null, 300, 200]
],
type: "spline"
},
point: {
show: false
}
});
.bb-lines-data2 {
stroke-dasharray: 2 4;
stroke-width: 2px;
}
<!doctype html>
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/billboard.js/dist/billboard.pkgd.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/billboard.js/dist/billboard.min.css">
</head>
<body>
<div id="chart"></div>
</body>
</html>
Using point show as false hides all the data points.
But what to do if I want to hide all but one datapoint.
For Example,
var chart = c3.generate({
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
['data2', 50, 20, 10, 40, 15, 25]
]
}
});
In the above line chart, how to highlight the data point where value is 100 and hide every other data point?
In C3, those circles have a class named c3-circle. So, using a D3 selection, you can set the opacity based on the bound datum:
var circles = d3.selectAll(".c3-circle")
.style("opacity", function(d){
return d.value === 100 ? 1 : 0;
})
Thus, only the circle corresponding to 100 is visible.
Here is the demo:
var chart = c3.generate({
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
['data2', 50, 20, 10, 40, 15, 25]
]
}
});
var circles = d3.selectAll(".c3-circle").style("opacity", function(d){
return d.value === 100 ? 1 : 0;
})
<script src="https://d3js.org/d3.v3.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://rawgit.com/masayuki0812/c3/master/c3.css">
<script src="https://rawgit.com/masayuki0812/c3/master/c3.js"></script>
<div id="chart"></div>
I'm trying to push the values on the x category axis to be on the sides of the bars, not in the middle. Apparently it is possible to put the ticks there, but can values go under the ticks as well?
var chart;
chart = c3.generate({
data: {
columns: [
['data', 30, 200, 100, 400, 150, 250]
],
type: 'bar'
},
bar: {
width: {
ratio: 0.98
}
},
axis: {
x: {
type: 'category',
categories: [10, 50, 100, 500, 2000, 5000],
tick: {
centered: false
}
}
},
legend: {
show: false
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.11/c3.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.11/c3.min.js"></script>
<div id="chart" class="c3" style="max-height: 280px; position: relative;"></div>
It's not the prettiest answer, and the last label gets chopped off (you'll have to investigate c3's padding options), but these 2 lines after you've rendered the chart do the trick:
// use c3's internal x scale to get the width of one bar
var width = chart.internal.x(1) - chart.internal.x(0);
// shuffle all the tick label tspans along by half a bar's width
d3.select(".c3-axis").selectAll(".tick text tspan").attr("dx", width/2);
var chart;
chart = c3.generate({
data: {
columns: [
['data', 30, 200, 100, 400, 150, 250]
],
type: 'bar'
},
bar: {
width: {
ratio: 0.98
}
},
axis: {
x: {
type: 'category',
categories: [10, 50, 100, 500, 2000, 5000],
tick: {
centered: false
}
}
},
legend: {
show: false
}
});
var width = chart.internal.x(1) - chart.internal.x(0);
d3.select(".c3-axis").selectAll(".tick text tspan").attr("dx", width/2);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.11/c3.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.11/c3.min.js"></script>
<div id="chart" class="c3" style="max-height: 280px; position: relative;"></div>
I want to make a simple graph, before advancing with the task I copied some of C3's chart samples which i save to an html file and open it with a browser and am ending up with a blank page.
An example of the code am trying to run is:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>d3 | c3 Timeseries Chart test</title>
<link href="c3.css" rel="stylesheet" type="text/css">
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.4.2/d3.js"></script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/c3/0.4.4/c3.min.js"></script>
<style>
body {font-family: monospace; line-height: 140%; font-size: 18px; }
</style>
</head>
<body>
<div class='chart'>
<div id='chart'></div>
</div>
<h4> Chart </h4>
<script type="text/javascript">
var chart = c3.generate({
data: {
x: 'x',
// xFormat: '%Y%m%d', // 'xFormat' can be used as custom format of 'x'
columns: [
['x', '2014-01-01', '2014-01-02', '2014-01-03', '2014-01-04', '2014-01-05', '2014-01-06'],
// ['x', '20130101', '20130102', '20130103', '20130104', '20130105', '20130106'],
['data1', 30, 200, 100, 400, 150, 250],
['data2', 130, 340, 200, 500, 250, 350],
['data3', 70, 220, 200, 100, 600, 512]
]
},
axis: {
x: {
type: 'timeseries',
tick: {
format: '%Y-%m-%d'
}
}
}
});
setTimeout(function () {
chart.load({
columns: [
['data4', 400, 500, 450, 700, 600, 100]
]
});
}, 1000);
</script>
</body>
</html>
</html>
Because C3.js is probably a huge file, downloading it takes a considerable amount of time. Meanwhile the browser runs your script, but because the file is still in a downloading state, c3 won't be defined.
To fix this, you have multiple options:
a) Put your script in a different file and add the defer tag to the script tag:
<script src="yourscript.js" defer="defer"></script>
b) Put your code in the window.onload function:
window.onload = function() {
// Your script goes here
}
I am trying to create a simple chart and it just doesn't work. Any help would be great. I followed the instructions found on the C3.js documentation website, but I still get a blank page.
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="https://rawgit.com/masayuki0812/c3/master/c3.css">
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script src="https://rawgit.com/masayuki0812/c3/master/c3.js"></script>
<script>
var chart = c3.generate({
bindto: '#chart',
data: {
columns: [
['data1', 30, 200, 100, 400, 150, 250],
['data2', 50, 20, 10, 40, 15, 25]
]
}
});
</script>
</head>
<body>
<div id="chart"></div>
</body>
</html>
First, I would check for cross-origin exceptions. This is usually cause by using scripts that are hosted on other websites. If you are having issues such as this, look for a Content Delivery Network (CDN). These sites host scripts that can be run on any website.
But I believe your problem is that you are running JavaScript code before the document has finished loading. There are two ways to ensure that an element is loaded before you start performing JavaScript on the DOM.
Script in the HEAD (Using Timeout)
Your HTML page's source should look like this. You will need to wait for the element to be loaded first. This utilized pure JavaScript and does not need jQuery.
<!DOCTYPE html>
<html>
<head>
<link href="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.10/c3.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.10/c3.min.js"></script>
<script type="text/javascript">
onReady('#chart', function() {
var chart = c3.generate({
data: {
columns: [
['data1', 300, 350, 300, 0, 0, 0],
['data2', 130, 100, 140, 200, 150, 50]
],
types: {
data1: 'area',
data2: 'area-spline'
}
},
axis: {
y: {
padding: {
bottom: 0
},
min: 0
},
x: {
padding: {
left: 0
},
min: 0,
show: false
}
}
});
});
// Set a timeout so that we can ensure that the `chart` element is created.
function onReady(selector, callback) {
var intervalID = window.setInterval(function() {
if (document.querySelector(selector) !== undefined) {
window.clearInterval(intervalID);
callback.call(this);
}
}, 500);
}
</script>
</head>
<body>
<div id="chart"></div>
</body>
</html>
Script at DOM End (Without Timeout)
You could also run the script following the chart element. This script will be guaranteed to run, because the target object #chart has already been parsed by the browser and loaded.
<!DOCTYPE html>
<html>
<head>
<link href="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.10/c3.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.10/c3.min.js"></script>
</head>
<body>
<div id="chart"></div>
<script type="text/javascript">
var chart = c3.generate({
data: {
columns: [
['data1', 300, 350, 300, 0, 0, 0],
['data2', 130, 100, 140, 200, 150, 50]
],
types: {
data1: 'area',
data2: 'area-spline'
}
},
axis: {
y: {
padding: {
bottom: 0
},
min: 0
},
x: {
padding: {
left: 0
},
min: 0,
show: false
}
}
});
</script>
</body>
</html>
Stack Overflow Snippet
Here is a working example. Make sure your paths are correct to your D3 and C3 files.
var chart = c3.generate({
data: {
columns: [
['data1', 300, 350, 300, 0, 0, 0],
['data2', 130, 100, 140, 200, 150, 50]
],
types: {
data1: 'area',
data2: 'area-spline'
}
},
axis: {
y: {
padding: {
bottom: 0
},
min: 0
},
x: {
padding: {
left: 0
},
min: 0,
show: false
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.10/c3.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/c3/0.4.10/c3.min.css" rel="stylesheet" />
<div id="chart"></div>