Commit ad528ad0f9c94904a9b7e205bb28cab57c2d011e

Authored by Antoine Goutenoir
1 parent e4138b41
Exists in master

fix: use DOMContentLoaded

Showing 1 changed file with 258 additions and 264 deletions   Show diff stats
flaskr/static/js/plots/emissions-per-distance.js
1 // export draw_emissions_per_distance 1 // export draw_emissions_per_distance
2 2
3 function draw_emissions_per_distance(divId, csvUrl) { 3 function draw_emissions_per_distance(divId, csvUrl) {
4 - (() => {  
5 - // let divId = "emissions_per_distance_histogram"; 4 + // let divId = "emissions_per_distance_histogram";
6 5
7 - // set the dimensions and margins of the graph  
8 - let margin = {top: 30, right: 62, bottom: 62, left: 72},  
9 - width = 960 - margin.left - margin.right,  
10 - height = 540 - margin.top - margin.bottom; 6 + // set the dimensions and margins of the graph
  7 + let margin = {top: 30, right: 62, bottom: 62, left: 72},
  8 + width = 960 - margin.left - margin.right,
  9 + height = 540 - margin.top - margin.bottom;
11 10
12 - function getTicks(maxValue, interval, startValue = 0) {  
13 - let range = [];  
14 - for (let i = startValue; i <= maxValue; i += interval) {  
15 - range.push(i);  
16 - }  
17 - return range; 11 + function getTicks(maxValue, interval, startValue = 0) {
  12 + let range = [];
  13 + for (let i = startValue; i <= maxValue; i += interval) {
  14 + range.push(i);
18 } 15 }
  16 + return range;
  17 + }
19 18
20 - function getBottomTicks(maxDistance) {  
21 - let range = getTicks(maxDistance, 2500, 2500);  
22 - range.push(500);  
23 - return range;  
24 - } 19 + function getBottomTicks(maxDistance) {
  20 + let range = getTicks(maxDistance, 2500, 2500);
  21 + range.push(500);
  22 + return range;
  23 + }
25 24
26 - function getLeftTicks(maxemissions) {  
27 - return getTicks(maxemissions, Math.floor((maxemissions / 8) / 1000) * 1000);  
28 - } 25 + function getLeftTicks(maxemissions) {
  26 + return getTicks(maxemissions, Math.floor((maxemissions / 8) / 1000) * 1000);
  27 + }
29 28
30 - function getRightTicks(maxemissionsPercent) {  
31 - return getTicks(maxemissionsPercent, 2); 29 + function getRightTicks(maxemissionsPercent) {
  30 + return getTicks(maxemissionsPercent, 2);
  31 + }
  32 +
  33 + function getAttendeeOnRight(sliceId, attendeeNumberPerGroup) {
  34 + let attendeeSum = 0;
  35 + let sliceInt = Math.floor(sliceId);
  36 + let sliceFloat = sliceId - sliceInt;
  37 + for (let i = sliceInt; i < attendeeNumberPerGroup.length; i++) {
  38 + attendeeSum += attendeeNumberPerGroup[i] * (1 - sliceFloat);
  39 + sliceFloat = 0;
32 } 40 }
  41 + return attendeeSum;
33 42
34 - function getAttendeeOnRight(sliceId, attendeeNumberPerGroup) {  
35 - let attendeeSum = 0;  
36 - let sliceInt = Math.floor(sliceId);  
37 - let sliceFloat = sliceId - sliceInt;  
38 - for (let i = sliceInt; i < attendeeNumberPerGroup.length; i++) {  
39 - attendeeSum += attendeeNumberPerGroup[i] * (1 - sliceFloat);  
40 - sliceFloat = 0;  
41 - }  
42 - return attendeeSum; 43 + }
43 44
  45 + function setupCursorBoxes(event, attendeeSum, attendeeNumberPerGroup, xScale, box, vertical, rightArea) {
  46 + // mousex = d3.mouse(this);
  47 + // const x = d3.mouse(this)[0];
  48 + // const y = d3.mouse(this)[1];
  49 + const x = d3.pointer(event)[0];
  50 + const y = d3.pointer(event)[1];
  51 + // var y = d3.event.pageY - document.getElementById(<id-of-your-svg>).getBoundingClientRect().y + 10
  52 + // x += 5;
  53 + vertical.style("left", x + "px");
  54 + rightArea.style("left", x + "px");
  55 + box.style("left", (x + 10) + "px");
  56 + box.style("top", (y - 20) + "px");
  57 + let sliceId = xScale.invert(x - d3.selectAll("g.yl.axis")._groups[0][0].getBoundingClientRect().right) / 500;
  58 + // let sliceId = xScale.invert(x * 1.025 - d3.selectAll("g.yl.axis")._groups[0][0].getBoundingClientRect().x- margin.left)/500 +1;
  59 + let attendeePercent = (getAttendeeOnRight(sliceId, attendeeNumberPerGroup) / attendeeSum * 100.0).toFixed(1);
  60 + if (x > d3.selectAll("g.yr.axis")._groups[0][0].getBoundingClientRect().x ||
  61 + x < d3.selectAll("g.yl.axis")._groups[0][0].getBoundingClientRect().right) {
  62 + rightArea.style("width", 0);
  63 + vertical.style("width", 0);
  64 + box.style("display", "none");
44 } 65 }
45 -  
46 - function setupCursorBoxes(event, attendeeSum, attendeeNumberPerGroup, xScale, box, vertical, rightArea) {  
47 - // mousex = d3.mouse(this);  
48 - // const x = d3.mouse(this)[0];  
49 - // const y = d3.mouse(this)[1];  
50 - const x = d3.pointer(event)[0];  
51 - const y = d3.pointer(event)[1];  
52 - // var y = d3.event.pageY - document.getElementById(<id-of-your-svg>).getBoundingClientRect().y + 10  
53 - // x += 5;  
54 - vertical.style("left", x + "px");  
55 - rightArea.style("left", x + "px");  
56 - box.style("left", (x + 10) + "px");  
57 - box.style("top", (y - 20) + "px");  
58 - let sliceId = xScale.invert(x - d3.selectAll("g.yl.axis")._groups[0][0].getBoundingClientRect().right) / 500;  
59 - // let sliceId = xScale.invert(x * 1.025 - d3.selectAll("g.yl.axis")._groups[0][0].getBoundingClientRect().x- margin.left)/500 +1;  
60 - let attendeePercent = (getAttendeeOnRight(sliceId, attendeeNumberPerGroup) / attendeeSum * 100.0).toFixed(1);  
61 - if (x > d3.selectAll("g.yr.axis")._groups[0][0].getBoundingClientRect().x ||  
62 - x < d3.selectAll("g.yl.axis")._groups[0][0].getBoundingClientRect().right) {  
63 - rightArea.style("width", 0);  
64 - vertical.style("width", 0);  
65 - box.style("display", "none");  
66 - }  
67 - else {  
68 - rightArea.style("width", d3.selectAll("g.yr.axis")._groups[0][0].getBoundingClientRect().x - x);  
69 - vertical.style("width", "2px");  
70 - box.style("display", "inherit");  
71 - }  
72 - box.text(attendeePercent + " % of attendees");  
73 - box.text(attendeePercent + " % of attendees");  
74 - // console.log(d3.selectAll("g.x.axis")._groups[0][0]);  
75 - // console.log(d3.selectAll("g.x.axis")._groups[0][0].getBoundingClientRect().x); 66 + else {
  67 + rightArea.style("width", d3.selectAll("g.yr.axis")._groups[0][0].getBoundingClientRect().x - x);
  68 + vertical.style("width", "2px");
  69 + box.style("display", "inherit");
76 } 70 }
  71 + box.text(attendeePercent + " % of attendees");
  72 + box.text(attendeePercent + " % of attendees");
  73 + // console.log(d3.selectAll("g.x.axis")._groups[0][0]);
  74 + // console.log(d3.selectAll("g.x.axis")._groups[0][0].getBoundingClientRect().x);
  75 + }
77 76
78 - function addVerticalLineAndListenCursor(xScale, attendeeNumberPerGroup, attendeeSum) {  
79 - let vertical = d3.select("#" + divId)  
80 - .append("div")  
81 - .attr("class", "remove")  
82 - .style("position", "absolute")  
83 - .style("z-index", "19")  
84 - .style("width", "2px")  
85 - .style("height", (height) + "px")  
86 - .style("top", (10 + margin.top) + "px")  
87 - .style("bottom", "30px")  
88 - .style("left", "0px")  
89 - .style("background", "#000"); 77 + function addVerticalLineAndListenCursor(xScale, attendeeNumberPerGroup, attendeeSum) {
  78 + let vertical = d3.select("#" + divId)
  79 + .append("div")
  80 + .attr("class", "remove")
  81 + .style("position", "absolute")
  82 + .style("z-index", "19")
  83 + .style("width", "2px")
  84 + .style("height", (height) + "px")
  85 + .style("top", (10 + margin.top) + "px")
  86 + .style("bottom", "30px")
  87 + .style("left", "0px")
  88 + .style("background", "#000");
90 89
91 - let rightArea = d3.select("#" + divId)  
92 - .append("div")  
93 - .attr("class", "remove")  
94 - .style("position", "absolute")  
95 - .style("z-index", "-50")  
96 - .style("width", "2000px")  
97 - .style("height", (height) + "px")  
98 - .style("top", (10 + margin.top) + "px")  
99 - .style("bottom", "30px")  
100 - .style("left", "0px")  
101 - .style("background", "rgba(60, 200, 60, 0.3)"); 90 + let rightArea = d3.select("#" + divId)
  91 + .append("div")
  92 + .attr("class", "remove")
  93 + .style("position", "absolute")
  94 + .style("z-index", "-50")
  95 + .style("width", "2000px")
  96 + .style("height", (height) + "px")
  97 + .style("top", (10 + margin.top) + "px")
  98 + .style("bottom", "30px")
  99 + .style("left", "0px")
  100 + .style("background", "rgba(60, 200, 60, 0.3)");
102 101
103 102
104 - let box = d3.select("#" + divId)  
105 - .append("div")  
106 - .attr("class", "remove")  
107 - .style("position", "absolute")  
108 - .style("z-index", "20")  
109 - .style("width", "150px")  
110 - .style("height", "22px")  
111 - .style("top", "10px")  
112 - .style("bottom", "30px")  
113 - .style("left", "0px")  
114 - .style("border", "1px solid grey")  
115 - .style("background", "rgba(255, 255, 255, 0.7)");  
116 - d3.select("#" + divId)  
117 - .on("mousemove", function (event) {  
118 - setupCursorBoxes(event, attendeeSum, attendeeNumberPerGroup, xScale, box, vertical, rightArea);  
119 - })  
120 - .on("mouseover", function (event) {  
121 - setupCursorBoxes(event, attendeeSum, attendeeNumberPerGroup, xScale, box, vertical, rightArea);  
122 -  
123 - });  
124 - } 103 + let box = d3.select("#" + divId)
  104 + .append("div")
  105 + .attr("class", "remove")
  106 + .style("position", "absolute")
  107 + .style("z-index", "20")
  108 + .style("width", "150px")
  109 + .style("height", "22px")
  110 + .style("top", "10px")
  111 + .style("bottom", "30px")
  112 + .style("left", "0px")
  113 + .style("border", "1px solid grey")
  114 + .style("background", "rgba(255, 255, 255, 0.7)");
  115 + d3.select("#" + divId)
  116 + .on("mousemove", function (event) {
  117 + setupCursorBoxes(event, attendeeSum, attendeeNumberPerGroup, xScale, box, vertical, rightArea);
  118 + })
  119 + .on("mouseover", function (event) {
  120 + setupCursorBoxes(event, attendeeSum, attendeeNumberPerGroup, xScale, box, vertical, rightArea);
125 121
  122 + });
  123 + }
126 124
127 - document.onreadystatechange = () => {  
128 - if (document.readyState === 'complete') {  
129 - let maxemissions = 0;  
130 - let maxemissionsPercent = 0;  
131 - let maxDistance = 0;  
132 - let svg = d3.select("#" + divId)  
133 - .append("svg")  
134 - .attr("id", divId + "-svg")  
135 - .attr("width", width + margin.left + margin.right)  
136 - .attr("height", height + margin.top + margin.bottom)  
137 - .append("g")  
138 - .attr("transform",  
139 - "translate(" + margin.left + "," + margin.top + ")"); 125 + document.addEventListener("DOMContentLoaded", () => {
  126 + let maxemissions = 0;
  127 + let maxemissionsPercent = 0;
  128 + let maxDistance = 0;
  129 + let svg = d3.select("#" + divId)
  130 + .append("svg")
  131 + .attr("id", divId + "-svg")
  132 + .attr("width", width + margin.left + margin.right)
  133 + .attr("height", height + margin.top + margin.bottom)
  134 + .append("g")
  135 + .attr("transform",
  136 + "translate(" + margin.left + "," + margin.top + ")");
140 137
141 - let emissionsPerGroup = [];  
142 - let attendeeNumberPerGroup = [];  
143 - let emissionsSum = 0;  
144 - let attendeeSum = 0;  
145 - let rows = []; 138 + let emissionsPerGroup = [];
  139 + let attendeeNumberPerGroup = [];
  140 + let emissionsSum = 0;
  141 + let attendeeSum = 0;
  142 + let rows = [];
146 143
147 - const on_csv_datum = function (datum) {  
148 - let trainAttendee = parseInt(datum["train trips_amount"]);  
149 - let planeAttendee = parseInt(datum["plane trips_amount"]);  
150 - if (trainAttendee === 0 && planeAttendee === 0) {  
151 - return;  
152 - }  
153 - let attendeeNumber = trainAttendee + planeAttendee;  
154 - let distance_km = datum.distance_km / attendeeNumber;  
155 - let co2_kg = parseFloat(datum.co2_kg);  
156 - if (co2_kg === "NaN" || distance_km / 500 > 37 || distance_km === "NaN") {  
157 - return;  
158 - }  
159 - rows.push(datum);  
160 - maxDistance = Math.max(maxDistance, distance_km);  
161 - emissionsSum += co2_kg;  
162 -  
163 - }; 144 + const on_csv_datum = function (datum) {
  145 + let trainAttendee = parseInt(datum["train trips_amount"]);
  146 + let planeAttendee = parseInt(datum["plane trips_amount"]);
  147 + if (trainAttendee === 0 && planeAttendee === 0) {
  148 + return;
  149 + }
  150 + let attendeeNumber = trainAttendee + planeAttendee;
  151 + let distance_km = datum.distance_km / attendeeNumber;
  152 + let co2_kg = parseFloat(datum.co2_kg);
  153 + if (co2_kg === "NaN" || distance_km / 500 > 37 || distance_km === "NaN") {
  154 + return;
  155 + }
  156 + rows.push(datum);
  157 + maxDistance = Math.max(maxDistance, distance_km);
  158 + emissionsSum += co2_kg;
164 159
165 - const on_csv_ready = function () {  
166 - for (let i = 0; i <= maxDistance / 500; i++) {  
167 - emissionsPerGroup[i] = 0;  
168 - attendeeNumberPerGroup[i] = 0;  
169 - }  
170 - rows.forEach((element, index) => {  
171 - let trainAttendee = parseInt(element["train trips_amount"]);  
172 - let planeAttendee = parseInt(element["plane trips_amount"]);  
173 - let attendeeNumber = trainAttendee + planeAttendee;  
174 - let distance_km = element.distance_km / attendeeNumber;  
175 - let co2_kg = parseFloat(element.co2_kg);  
176 - emissionsPerGroup[Math.floor(distance_km / 500)] += parseFloat(co2_kg);  
177 - attendeeNumberPerGroup[Math.floor(distance_km / 500)] += attendeeNumber;  
178 - attendeeSum += attendeeNumber;  
179 - });  
180 - emissionsPerGroup.forEach((element, index) => {  
181 - maxemissions = Math.max(maxemissions, element);  
182 - maxemissionsPercent = Math.max(maxemissionsPercent, element / emissionsSum * 100.0)  
183 - });  
184 - maxDistance += 2000;  
185 - // console.log(maxDistance); 160 + };
186 161
187 - //Title  
188 - svg.append("text")  
189 - .attr("transform",  
190 - "translate(" + (70 + margin.left) + ", -12)")  
191 - .style("text-anchor", "middle")  
192 - .style("font-weight", "bold")  
193 - .style("font-size", "130%")  
194 - .text("Emissions per distance"); 162 + const on_csv_ready = function () {
  163 + for (let i = 0; i <= maxDistance / 500; i++) {
  164 + emissionsPerGroup[i] = 0;
  165 + attendeeNumberPerGroup[i] = 0;
  166 + }
  167 + rows.forEach((element, index) => {
  168 + let trainAttendee = parseInt(element["train trips_amount"]);
  169 + let planeAttendee = parseInt(element["plane trips_amount"]);
  170 + let attendeeNumber = trainAttendee + planeAttendee;
  171 + let distance_km = element.distance_km / attendeeNumber;
  172 + let co2_kg = parseFloat(element.co2_kg);
  173 + emissionsPerGroup[Math.floor(distance_km / 500)] += parseFloat(co2_kg);
  174 + attendeeNumberPerGroup[Math.floor(distance_km / 500)] += attendeeNumber;
  175 + attendeeSum += attendeeNumber;
  176 + });
  177 + emissionsPerGroup.forEach((element, index) => {
  178 + maxemissions = Math.max(maxemissions, element);
  179 + maxemissionsPercent = Math.max(maxemissionsPercent, element / emissionsSum * 100.0)
  180 + });
  181 + maxDistance += 2000;
  182 + // console.log(maxDistance);
195 183
196 - // X axis: scale and draw:  
197 - let x = d3.scaleLinear()  
198 - .domain([0, maxDistance])  
199 - .range([0, width]);  
200 - let xAxis = d3.axisBottom(x)  
201 - .tickValues(getBottomTicks(maxDistance));  
202 - svg.append("g")  
203 - .attr("transform", "translate(0," + height + ")")  
204 - .attr("class", "x axis")  
205 - .call(xAxis);  
206 - d3.selectAll("g.x.axis")  
207 - .selectAll(".tick")  
208 - .filter(function (d) {  
209 - return d === 0;  
210 - })  
211 - .remove(); 184 + //Title
  185 + svg.append("text")
  186 + .attr("transform",
  187 + "translate(" + (70 + margin.left) + ", -12)")
  188 + .style("text-anchor", "middle")
  189 + .style("font-weight", "bold")
  190 + .style("font-size", "130%")
  191 + .text("Emissions per distance");
212 192
213 - // Y axis Left  
214 - let yl = d3.scaleLinear()  
215 - .domain([0, maxemissions])  
216 - .range([height, 0]);  
217 - let ylAxis = d3.axisLeft(yl)  
218 - .tickValues(getLeftTicks(maxemissions));  
219 - svg.append("g")  
220 - .attr("class", "yl axis")  
221 - .call(ylAxis); 193 + // X axis: scale and draw:
  194 + let x = d3.scaleLinear()
  195 + .domain([0, maxDistance])
  196 + .range([0, width]);
  197 + let xAxis = d3.axisBottom(x)
  198 + .tickValues(getBottomTicks(maxDistance));
  199 + svg.append("g")
  200 + .attr("transform", "translate(0," + height + ")")
  201 + .attr("class", "x axis")
  202 + .call(xAxis);
  203 + d3.selectAll("g.x.axis")
  204 + .selectAll(".tick")
  205 + .filter(function (d) {
  206 + return d === 0;
  207 + })
  208 + .remove();
222 209
223 - // Y axis Right  
224 - let yr = d3.scaleLinear()  
225 - .domain([0, maxemissionsPercent])  
226 - .range([height, 0]);  
227 - let yrAxis = d3.axisRight(yr)  
228 - .tickValues(getRightTicks(maxemissionsPercent));  
229 - svg.append("g")  
230 - .attr("transform", "translate(" + width + ", 0)")  
231 - .attr("class", "yr axis")  
232 - .call(yrAxis); 210 + // Y axis Left
  211 + let yl = d3.scaleLinear()
  212 + .domain([0, maxemissions])
  213 + .range([height, 0]);
  214 + let ylAxis = d3.axisLeft(yl)
  215 + .tickValues(getLeftTicks(maxemissions));
  216 + svg.append("g")
  217 + .attr("class", "yl axis")
  218 + .call(ylAxis);
233 219
234 - svg.append("text")  
235 - .attr("transform",  
236 - "translate(" + (width / 2) + " ," +  
237 - (height + margin.top + 12) + ")")  
238 - .style("text-anchor", "middle")  
239 - .text("Distance travelled (km)"); 220 + // Y axis Right
  221 + let yr = d3.scaleLinear()
  222 + .domain([0, maxemissionsPercent])
  223 + .range([height, 0]);
  224 + let yrAxis = d3.axisRight(yr)
  225 + .tickValues(getRightTicks(maxemissionsPercent));
  226 + svg.append("g")
  227 + .attr("transform", "translate(" + width + ", 0)")
  228 + .attr("class", "yr axis")
  229 + .call(yrAxis);
240 230
241 - svg.append("text")  
242 - .attr("transform",  
243 - "translate(" + (width) + ", 0), rotate(-90)")  
244 - .attr("x", 0 - (height / 2))  
245 - .attr("y", 42)  
246 - .style("text-anchor", "middle")  
247 - .text("Share of emission [%]"); 231 + svg.append("text")
  232 + .attr("transform",
  233 + "translate(" + (width / 2) + " ," +
  234 + (height + margin.top + 12) + ")")
  235 + .style("text-anchor", "middle")
  236 + .text("Distance travelled (km)");
248 237
249 - svg.append("text")  
250 - .attr("transform", "rotate(-90)")  
251 - .attr("y", 0 - margin.left)  
252 - .attr("x", 0 - (height / 2))  
253 - .attr("dy", "1em")  
254 - .style("text-anchor", "middle")  
255 - .text("Emission (tCO2e)");  
256 - // set the parameters for the histogram  
257 - var histogram = d3.histogram()  
258 - .domain(x.domain()) // then the domain of the graphic  
259 - .thresholds(x.ticks(Math.floor(maxDistance / 500))); // then the numbers of bins 238 + svg.append("text")
  239 + .attr("transform",
  240 + "translate(" + (width) + ", 0), rotate(-90)")
  241 + .attr("x", 0 - (height / 2))
  242 + .attr("y", 42)
  243 + .style("text-anchor", "middle")
  244 + .text("Share of emission [%]");
260 245
261 - let histolol = histogram(0);  
262 - // console.log(histolol);  
263 - let barSettings = [];  
264 - emissionsPerGroup.forEach((element, index) => {  
265 - barSettings[index] =  
266 - {  
267 - height: element,  
268 - leftBorder: histolol[index].x0,  
269 - rightBorder: histolol[index].x1,  
270 - };  
271 - // console.log(index);  
272 - // console.log(barSettings[index]);  
273 - });  
274 - svg.selectAll("rect")  
275 - .data(barSettings)  
276 - .enter()  
277 - .append("rect")  
278 - .attr("x", 1)  
279 - .attr("transform", function (d) {  
280 - return "translate(" + x(d.leftBorder) + "," + yl(d.height) + ")";  
281 - })  
282 - .attr("width", function (d) {  
283 - return x(d.rightBorder) - x(d.leftBorder) - 1;  
284 - })  
285 - .attr("height", function (d) {  
286 - return (height - yl(d.height));  
287 - })  
288 - .style("z-index", "500")  
289 - .style("fill", "#4444E5");  
290 - addVerticalLineAndListenCursor(x, attendeeNumberPerGroup, attendeeSum);  
291 - }; 246 + svg.append("text")
  247 + .attr("transform", "rotate(-90)")
  248 + .attr("y", 0 - margin.left)
  249 + .attr("x", 0 - (height / 2))
  250 + .attr("dy", "1em")
  251 + .style("text-anchor", "middle")
  252 + .text("Emission (tCO2e)");
  253 + // set the parameters for the histogram
  254 + var histogram = d3.histogram()
  255 + .domain(x.domain()) // then the domain of the graphic
  256 + .thresholds(x.ticks(Math.floor(maxDistance / 500))); // then the numbers of bins
292 257
293 - d3.csv(csvUrl, on_csv_datum)  
294 - .then(on_csv_ready);  
295 - } 258 + let histolol = histogram(0);
  259 + // console.log(histolol);
  260 + let barSettings = [];
  261 + emissionsPerGroup.forEach((element, index) => {
  262 + barSettings[index] =
  263 + {
  264 + height: element,
  265 + leftBorder: histolol[index].x0,
  266 + rightBorder: histolol[index].x1,
  267 + };
  268 + // console.log(index);
  269 + // console.log(barSettings[index]);
  270 + });
  271 + svg.selectAll("rect")
  272 + .data(barSettings)
  273 + .enter()
  274 + .append("rect")
  275 + .attr("x", 1)
  276 + .attr("transform", function (d) {
  277 + return "translate(" + x(d.leftBorder) + "," + yl(d.height) + ")";
  278 + })
  279 + .attr("width", function (d) {
  280 + return x(d.rightBorder) - x(d.leftBorder) - 1;
  281 + })
  282 + .attr("height", function (d) {
  283 + return (height - yl(d.height));
  284 + })
  285 + .style("z-index", "500")
  286 + .style("fill", "#4444E5");
  287 + addVerticalLineAndListenCursor(x, attendeeNumberPerGroup, attendeeSum);
296 }; 288 };
297 289
298 - })(); 290 + d3.csv(csvUrl, on_csv_datum)
  291 + .then(on_csv_ready);
  292 + });
299 293
300 } 294 }
301 \ No newline at end of file 295 \ No newline at end of file