Tidy up charts code, including avoiding js error on tabular data view
[civicrm-core.git] / templates / CRM / common / chart.tpl
CommitLineData
dc61ee93
RLAR
1{*
2 +--------------------------------------------------------------------+
3 | CiviCRM version 5 |
4 +--------------------------------------------------------------------+
5 | Copyright CiviCRM LLC (c) 2004-2019 |
6 +--------------------------------------------------------------------+
7 | This file is a part of CiviCRM. |
8 | |
9 | CiviCRM is free software; you can copy, modify, and distribute it |
10 | under the terms of the GNU Affero General Public License |
11 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
12 | |
13 | CiviCRM is distributed in the hope that it will be useful, but |
14 | WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
16 | See the GNU Affero General Public License for more details. |
17 | |
18 | You should have received a copy of the GNU Affero General Public |
19 | License and the CiviCRM Licensing Exception along |
20 | with this program; if not, contact CiviCRM LLC |
21 | at info[AT]civicrm[DOT]org. If you have questions about the |
22 | GNU Affero General Public License or the licensing of CiviCRM, |
23 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
24 +--------------------------------------------------------------------+
25*}
26<script src="{$config->resourceBase}/bower_components/d3/d3.min.js"></script>
27<script src="{$config->resourceBase}/bower_components/crossfilter2/crossfilter.min.js"></script>
28<script src="{$config->resourceBase}/bower_components/dc-2.1.x/dc.min.js"></script>
29<style src="{$config->resourceBase}/bower_components/dc-2.1.x/dc.min.css"></style>
30{literal}
31<style>
32 .dc-chart path.domain {
33 fill: none;
34 stroke: black;
35 }
36</style>
37<script type="text/javascript">
38function createChart( chartID, divName, xSize, ySize, data ) {
39
40 var div = document.getElementById(divName);
41 if (!div) {
42 console.log("no element found for chart id ", divName);
43 return;
44 }
45
0cf05243
RLAR
46 // Figure out suitable size based on container size.
47 var w = Math.min(div.clientWidth - 32, 800);
48 var h = Math.min(400, parseInt(w / 2));
dc61ee93
RLAR
49
50 var chartNode = document.createElement('div');
51 var heading = document.createElement('h2');
52 heading.textContent = data.title;
53 heading.style.marginBottom = '1rem';
54 heading.style.textAlign = 'center';
55 div.style.width = w + 'px';
56 div.style.marginLeft = 'auto';
57 div.style.marginRight = 'auto';
58
59 var links = document.createElement('div');
0cf05243
RLAR
60 links.style.textAlign = 'center';
61 links.style.marginBottom = '1rem';
dc61ee93
RLAR
62 var linkSVG = document.createElement('a');
63 linkSVG.href = '#';
64 linkSVG.textContent = 'Download chart (SVG)';
65 linkSVG.addEventListener('click', e => {
66 e.preventDefault();
67 e.stopPropagation();
68 // Create an image.
69 var svg = div.querySelector('svg');
70 var xml = new XMLSerializer().serializeToString(svg);
71 var image64 = 'data:image/svg+xml;base64,' + btoa(xml);
72
73 downloadImageUrl('image/svg+xml', image64, data.title.replace(/[^a-zA-Z0-9-]+/g, '') + '.svg');
74 });
75 function downloadImageUrl(mime, url, filename) {
76 var downloadLink = document.createElement('a');
77 downloadLink.download = filename;
78 downloadLink.href = url;
79 downloadLink.downloadurl = [mime, downloadLink.download, url].join(':');
80 document.body.append(downloadLink);
81 downloadLink.click();
82 document.body.removeChild(downloadLink);
83 }
84 var linkPNG = document.createElement('a');
85 linkPNG.href = '#';
86 linkPNG.textContent = 'Download chart (PNG)';
87 linkPNG.addEventListener('click', e => {
88 e.preventDefault();
89 e.stopPropagation();
90 // Create an image.
91
92 var canvas = document.createElement('canvas');
93 canvas.width = w;
94 canvas.height = h;
95 div.appendChild(canvas);
96
97 var svg = div.querySelector('svg');
98 var xml = new XMLSerializer().serializeToString(svg);
99 var svg64 = btoa(xml);
100 var b64Start = 'data:image/svg+xml;base64,';
101 var image64 = b64Start + svg64;
102
103 var img = document.createElement('img');
104 img.onload = function() {
105 canvas.getContext('2d').drawImage(img, 0, 0);
106 // canvas.style.display = 'block';
107 var imgURL = canvas.toDataURL('image/png');
108 downloadImageUrl('image/png', imgURL, data.title.replace(/[^a-zA-Z0-9-]+/g, '') + '.png');
109 div.removeChild(canvas);
110 };
111 img.src = image64;
112 });
113
114 links.appendChild(linkSVG);
115 links.appendChild(document.createTextNode(' | '));
116 links.appendChild(linkPNG);
dc61ee93
RLAR
117
118 var crossfilterData, ndx, dataDimension, dataGroup, chart;
119 ndx = crossfilter(data.values[0]);
120 dataDimension = ndx.dimension(d => d.label);
121 dataGroup = dataDimension.group().reduceSum(d => d.value);
122 var ordinals = data.values[0].map(d => d.label);
123
124 if (data.type === 'barchart') {
125 chart = dc.barChart(chartNode)
126 .width(w)
127 .height(h)
128 .dimension(dataDimension)
129 .group(dataGroup)
130 .gap(4) // px
131 .x(d3.scale.ordinal(ordinals).domain(ordinals))
132 .xUnits(dc.units.ordinal)
133 .margins({top: 10, right: 30, bottom: 30, left: 90})
134 .elasticY(true)
135 .renderLabel(false)
136 .renderHorizontalGridLines(true)
137 .title(item=> item.key + ': ' + item.value)
138 //.turnOnControls(true)
139 .renderTitle(true);
140 }
141 else if (data.type === 'piechart') {
142 chart = dc.pieChart(chartNode)
143 .width(w)
144 .height(h)
145 .radius(parseInt(h / 2) - 5) // define pie radius
146 .innerRadius(parseInt(h / 4) - 5) // optional
147 .externalRadiusPadding(5)
148 .legend(dc.legend().legendText(d => d.name).y(5))
149 .dimension(dataDimension)
150 .group(dataGroup)
151 .renderLabel(false)
152 .title(item=> item.key + ': ' + item.value)
153 .turnOnControls(true)
154 .renderTitle(true);
155 }
156 // Delay rendering so that animation looks good.
0cf05243
RLAR
157 window.setTimeout(() => {
158 div.appendChild(heading);
159 div.appendChild(chartNode);
160 div.appendChild(links);
161
162 dc.renderAll();
163 }, 1500);
dc61ee93
RLAR
164}
165</script>
166{/literal}