PageSourceSearch

https://electoral-simulator.firebaseapp.com/js/showSankey.js

js electoral-simulator.firebaseapp.com collected 2026-10-03 14:05:33 UTC 8,718 bytes, 320 lines download raw bytes

1var zoom = {};
2		var drag = {};
3		var svg = {};
4
5				  
6		function showSankey(energy)
7		{
8		
9			$('.d3-tip-nodes').remove(); //clear olds tips
10			// var chartBox = d3.select("#sankey").node().getBoundingClientRect();
11			var margin = {top: 10, right: 10, bottom: 10, left: 20};
12			var width = 800;
13			var height = 300;
14			
15		  var linkTooltipOffset = 72,
16			  nodeTooltipOffset = 130;
17			  
18		  //Tooltip function:
19		  //D3 sankey diagram with view options (Austin Czarnecki’s Block cc6371af0b726e61b9ab)
20		  //https://bl.ocks.org/austinczarnecki/cc6371af0b726e61b9ab
21		  var tipLinks = d3.tip()
22			  .attr('class', 'd3-tip')
23			  .attr('id', 'transferTips')
24			  .offset([-10,0]);
25
26		  var tipNodes = d3.tip()
27			  .attr('class', 'd3-tip d3-tip-nodes')
28			   .attr('id', 'transferTips')
29			  .offset([-10, 0]);
30			
31			
32		  function formatAmount(val) {
33			  //return val.toLocaleString("en-US", {style: 'currency', currency: "USD"}).replace(/\.[0-9]+/, "");
34			  return parseFloat(val).toFixed(0) + " votes";
35		  };
36			  
37			// "➡" 
38			tipLinks.html(function(d) {
39			  var title, candidate;
40			  if (energy.links.indexOf(d.source.name) > -1) {
41				candidate = d.source.name;
42				title = d.target.name;
43			  } else {
44				candidate = d.target.name;
45				title = d.source.name;
46			  }
47				var html =  '<div class="table-wrapper">'+
48					'<h1>'+title+'</h1>'+
49					'<table>'+
50						'<tr>'+
51							'<td class="col-left">'+candidate+'</td>'+
52							'<td align="right">'+formatAmount(d.value)+'</td>'+
53						'</tr>'+
54					'</table>'+
55					'</div>';
56			  return html;
57			});
58
59			tipNodes.html(function(d) {
60			  var object = d3.entries(d),
61				  nodeName = object[1].value,
62				  linksTo = object[3].value,
63				  linksFrom = object[4].value,
64				  html;
65
66			  html =  '<div class="table-wrapper">'+
67					  '<h1>'+nodeName+'</h1>'+
68					  '<table>';
69			  if (linksFrom.length > 0 & linksTo.length > 0) {
70				html+= '<tr><td><h2>Input:</h2></td><td></td></tr>'
71			  }
72			  for (i = 0; i < linksFrom.length; ++i) {
73				html += '<tr>'+
74				  '<td class="col-left">'+linksFrom[i].source.name+'</td>'+
75				  '<td align="right">'+formatAmount(linksFrom[i].value)+'</td>'+
76				'</tr>';
77			  }
78			  if (linksFrom.length > 0 & linksTo.length > 0) {
79				html+= '<tr><td><h2>Output:</h2></td><td></td></tr>'
80			  }
81			  for (i = 0; i < linksTo.length; ++i) {
82				html += '<tr>'+
83						  '<td class="col-left">'+linksTo[i].target.name+'</td>'+
84						  '<td align="right">'+formatAmount(linksTo[i].value)+'</td>'+
85						'</tr>';
86			  }
87			  html += '</table></div>';
88			  return html;
89			});
90			
91			// function zoomed() {
92			//   svg.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
93			// }
94
95			function dragstarted(d) {
96			  d3.select(this).classed("dragging", true);
97			}
98
99			function dragged(d) {
100			  d3.select(this).attr("cx", d.x = d3.event.x).attr("cy", d.y = d3.event.y);
101			}
102
103			function dragended(d) {
104			  d3.select(this).classed("dragging", false);
105			}	
106			
107			drag = d3.drag()
108			.subject(function(d) { return d; })
109			.on("drag", dragged)
110			.on("start", dragstarted)
111			.on("end", dragended);
112			
113			// zoom = d3.behavior.zoom()
114			// 	.scaleExtent([0, 5])
115			// 	.center([width / 2, height / 2])
116			// 	.on("zoom", zoomed);
117			
118		var formatNumber = d3.format(",.0f"),
119			format = function(d) { return formatNumber(d) + " votes transfered"; },
120			color = "#000000"
121		
122		svg = d3.select("#sankey").append("svg")
123			.attr("id", "snakeysvg")
124			.attr("width", width + 40)
125			.attr("height", height + 40)
126			.call(tipLinks)
127			.call(tipNodes)
128		  .append("g")
129			.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
130
131		var sankey = d3.sankey()
132			.nodeWidth(40)
133			.nodePadding(15)
134			.size([width, height]);
135
136		var path = sankey.link();
137		  sankey
138			  .nodes(energy.nodes)
139			  .links(energy.links)
140			  .layout(32);
141
142		var fontScale = d3.scaleLinear().domain(d3.extent(energy.nodes, function(d) { return d.value })).range([18, 30]);
143
144		  var link = svg.append("g").selectAll(".link")
145			  .data(energy.links)
146			.enter().append("path")
147			  .attr("class", "link")
148			  .attr("d", path)
149			  .style("stroke", function(d){ return d.source.color; })
150			  .style("stroke-width", function(d) { return Math.max(1, d.dy); })
151			  .sort(function(a, b) { return b.dy - a.dy; })
152			  .on('mousemove', function(event) {
153				tipLinks
154				  .style("top", (d3.event.pageY - linkTooltipOffset) + "px")
155				  .style("left", function () {
156					var left = (Math.max(d3.event.pageX - linkTooltipOffset, 10)); 
157					left = Math.min(left, window.innerWidth - $('.d3-tip').width() - 20)
158					return left + "px"; })
159				})
160			  .on('mouseover', tipLinks.show)
161			  .on('mouseout', tipLinks.hide);
162			  
163		  var node = svg.append("g").selectAll(".node")
164			  .data(energy.nodes)
165			.enter().append("g")
166			  .attr("class", "node")
167			  .attr("transform", function(d) {
168				  return "translate(" + d.x + "," + d.y + ")";
169			  })
170			.on('mousemove', function(event) {
171				tipNodes
172				  .style("top", (d3.event.pageY - $('.d3-tip-nodes').height() - 20) + "px")
173				  .style("left", function () {
174					var left = d3.event.pageX - 150; 
175					// left = Math.max(left, window.innerWidth - $('.d3-tip').width() - 20)
176					return left + "px"; })
177				})
178			.on('mouseover', tipNodes.show)
179			.on('mouseout', tipNodes.hide)
180			.call(d3.drag()
181			  .subject(function(d) { return d; })
182			  .on("start", function() { 
183				d3.event.sourceEvent.stopPropagation();
183  //Disable drag sankey on node select
184				this.parentNode.appendChild(this); })
185			  .on("drag", dragmove));
186
187		  node.append("rect")
188			  .attr("height", function(d) { return d.dy; })
189			  .attr("width", sankey.nodeWidth())
190			  .style("fill", function(d) {
191				  if (d.color == undefined)
192					return d.color = color(d.name.replace(/ .*/, "")); //get new color if node.color is null
193				  return d.color;
194			  })
195			  .style("stroke", function(d) { return d3.rgb(d.color).darker(2); });
196
197		  node.append("text")
198			  .attr("class","nodeValue")
199			  .text(function(d) { return d.name + "\n" + format(d.value); });
200
201		  node.selectAll("text.nodeValue")
202			  .attr("x", sankey.nodeWidth() / 2)
203			  .attr("y", function (d) { return (d.dy / 2) })
204			  .text(function (d) { return formatNumber(d.value); })
205			  .attr("dy", 5)
206			  .attr("text-anchor", "middle");
207
208		  node.append("text")
209			  .attr("class","nodeLabel")
210			  .style("fill", function(d) {
211					return d3.rgb(d.color).darker(2.4);
212			  })
213			  .style("font-size", function(d) {
214					return fontScale(d.value) + "px";
215			  });
216			  
217		  node.selectAll("text.nodeLabel")	
218			  .attr("x", -6)
219			  .attr("y", function(d) { return d.dy / 2; })
220			  .attr("dy", ".35em")
221			  .attr("text-anchor", "end")
222			  .attr("transform", null)
223			  .text(function(d) { return d.name; })
224			.filter(function(d) { return d.x < width / 2; })
225			  .attr("x", 6 + sankey.nodeWidth())
226			  .attr("text-anchor", "start");
227			function dragmove(d) {
228				d3.select(this)
229					.attr("transform", "translate(" + d.x + "," +
230					   (d.y = Math.max(0, Math.min(height - d.dy, d3.event.y))) + ")");
231				sankey.relayout();
232				link.attr("d", path);
233			};
234
235			// fitZoom();
236		}
237
238		function getData() {
239			return {
240				"nodes": [{
241				"node": 0,
242				"name": "Yellow Party",
243				color: "#faa71a"
244			}, {
245				"node": 1,
246				"name": "Red Party",
247				color:"#ed2224"
248			}, {
249				"node": 2,
250				"name": "Coral Party",
251				color: "#ff7f50"
252			}, {
253				"node": 3,
254				"name": "Blue Party",
255				color: "#4a82b5"
256			}, {
257				"node": 4,
258				"name": "Pink Party",
259				color: "#bd4289"
260			}, {
261				"node": 5,
262				"name": "Yellow Party",
263				color: "#faa71a"
264			}, {
265				"node": 6,
266				"name": "Red Party",
267				color: "#ed2224"
268			}, {
269				"node": 7,
270				"name": "Coral Party",
271				color: "#ff7f50"
272			},{
273				"node": 8,
274				"name": "Blue Party",
275				color: "#4a82b5"
276			},{
277				"node": 9,
278				"name": "Pink Party",
279				color: "#bd4289"
280			}
281
282			],
283				
284
285
286
287	"links":[
288{"source":2,"target":5,"value":22},
289{"source":1,"target":5,"value":114},
290{"source":0,"target":9,"value":146},
291{"source":3,"target":7,"value":201},
292{"source":1,"target":7,"value":147},
293{"source":1,"target":9,"value":122},
294{"source":1,"target":8,"value":129},
295{"source":2,"target":8,"value":140},
296{"source":3,"target":9,"value":25},
297{"source":3,"target":6,"value":30},
298{"source":2,"target":9,"value":25},
299{"source":0,"target":8,"value":25},
300{"source":0,"target":6,"value":25},
301{"source":3,"target":5,"value":26},
302{"source":4,"target":7,"value":21},
303{"source":4,"target":5,"value":135},
304{"source":4,"target":6,"value":19},
305{"source":4,"target":8,"value":21},
306{"source":2,"target":6,"value":22},
307{"source":0,"target":7,"value":22}]
308
309
310
311
312
313
314
315
316			};
317		};
318
319
320		

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.