PageSourceSearch

https://xfold.github.io/Web-DiscoveringAndInterpretingConceptualBiases/static/js/piechart.js

js xfold.github.io collected 2026-10-03 10:11:31 UTC 6,039 bytes, 211 lines download raw bytes

1class SentimentPieChart{
2	constructor(height, width, margin, element_selector){
3		$(element_selector).empty();
4
5		this.height = height;
6    	this.width = width;
7    	this.margin = margin;
8    	this.radius = Math.min(this.width, this.height) / 2 - this.margin;
9
10    	this.svg = d3.select(element_selector)
11			.attr("viewBox", [0, 0, this.width, this.height])
12		        .attr("perserveAspectRatio", "xMinYMid")
13		        .attr("width", this.width)
14		        .attr("height", this.height)
15		      .append("g")
16		        .attr("transform", "translate(" + this.width / 2 + "," + this.height / 2 + ")");
17
18		this.svg.append("g")
19			.attr("class", "slices");
20		this.svg.append("g")
21			.attr("class", "labels");
22		this.svg.append("g")
23			.attr("class", "lines");
24
25		this.color = d3.scaleOrdinal()
26			.domain(['strongly negative', 'negative', 'slightly negative', 'neutral','slightly positive', 'positive', 'strongly positive'], )
27			.range([ '#DC143C', '#FF6347', '#FFA07A', '#EFE199', '#ADFF2F', '#32CD32', '#228B22'] );
28
29		this.pie = d3.pie()
30			.sort(null)
31			.value(function(d) {
32				return d.accfreq;
33			});
34
35		this.arc = d3.arc()
36			.outerRadius(this.radius * 0.7)
37			.innerRadius(this.radius * 0.3);
38
39		this.arcOver = d3.arc()
40			.innerRadius(this.radius * 0.3)
41			.outerRadius(this.radius * 0.8);
42
43		var radius = this.radius;
44		this.outerArc = d3.arc()
45			.innerRadius(this.radius * 0.9)
46			.outerRadius(function(d){
47				var modifier = 0;
48				if(d.data.word.includes('strongly')) modifier = 2;
49				if(d.data.word.includes('slightly')) modifier = -1;
50				if(d.data.word == 'positive' || d.data.word == 'negative' ) modifier = 0.3;
51				return radius * 0.9  + modifier*30;
52			});
53
54		this.key = function(d){ return d.data.word; };
55
56	};		
57
58	binMe(data, size="all", sort_property = 'freq', filterneutrals=false,
59		bins= [-1,-0.6,-0.3, -0.005, 0.005,0.3,0.6,1], 
60		names = ['strongly negative', 'negative', 'slightly negative', 'neutral','slightly positive', 'positive', 'strongly positive'], 
61		){
62		var data2 = data.sort(fancysort(sort_property));
63		if(size!='all')data2 = data2.slice(0, Math.min(data2.length, size) );
64
65		var aggrdata = [];
66		for(var i = 0; i < bins.length-1; i++){
67
68			if(names[i] == 'neutral' && filterneutrals) continue;
69
70			var bin1 = bins[i];	
71			var bin2 = bins[i+1];
72			var accf = [];
73			var accs = [];
74			for(var j = 0; j < data2.length; j++){
75				var w = data2[j];
76				if(w['sent'] >= bin1 && w['sent'] < bin2 ){
77					accf.push(w['freq']);
78					accs.push( w['sent'] );
79				}
80			}
81			var accfreq = accf.reduce((a, b) => a + b, 0);
82			
83			var avgsent = undefined;
84			if(accs.length > 0) avgsent = accs.reduce((a, b) => a + b, 0) / accs.length;
85			if(accfreq>0)aggrdata.push({ word: names[i], accfreq: accfreq, avgsent: avgsent , relfreq: 0} );
86		}
87
88		var totf = 0;
89		for(var i = 0; i< aggrdata.length; i++){
90			totf += aggrdata[i]['accfreq'];
91		}
92		for(var i = 0; i< aggrdata.length; i++){
93			var relfreq = (aggrdata[i]['accfreq'] / totf * 100).toFixed(2);
94			aggrdata[i]['relfreq'] = relfreq;
95		}
96		
97		return aggrdata;
98	}
99
100	change(data, size="all", sort_property="freq", filterneutrals=false, binme = true) {
101		var radius = this.radius;
102		var svg = this.svg;
103		var height = this.height;
104    	var width = this.width;
105    	var margin = this.margin;
106    	var color = this.color;
107    	var pie = this.pie;
108    	var key = this.key;
109    	var outerArc = this.outerArc;
110    	var arc = this.arc;
111    	var arcOver = this.arcOver;
112
113    	//preprocess the data, cut by the size
114    	if(binme){
115    		var data = this.binMe(data, size, sort_property, filterneutrals);
116    	}
117
118		/* ------- PIE SLICES -------*/
119		var slice = svg.select(".slices").selectAll("path.slice")
120			.data(pie(data), key);
121
122		slice.enter()
123			.insert("path")
124			.style("fill", function(d) { return color(d.data.word); })
125			.attr("class", "slice")
126			.on("mouseover", function(d) {
127            	d3.select(this).transition()
128	               .duration(500)
129	               .attr("d", arcOver);
130             })
131			.on("mouseout", function(d) {
132	            	d3.select(this).transition()
133		               .duration(500)
134		               .attr("d", arc);
135	             });;
136
137		slice		
138			.transition().duration(1000)
139			.attrTween("d", function(d) {
140				this._current = this._current || d;
141				var interpolate = d3.interpolate(this._current, d);
142				this._current = interpolate(0);
143				return function(t) {
144					return arc(interpolate(t));
145				};
146			})
147
148		slice.exit()
149			.remove();
150
151		/* ------- TEXT LABELS -------*/
152
153		var text = svg.select(".labels").selectAll("text")
154			.data(pie(data), key);
155
156		text.enter()
157			.append("text")
158			.attr("dy", ".35em")
159			.attr("font-size", "10px")
160			.text(function(d) {
161				return d.data.word + " ("+d.data.relfreq+"%)";
162			});
163		
164		function midAngle(d){
165			return d.startAngle + (d.endAngle - d.startAngle)/2;
166		}
167
168		
169		text.transition().duration(1000)
170			.attr('transform', function(d) {
171	            var pos = outerArc.centroid(d);
172	            var midangle = d.startAngle + (d.endAngle - d.startAngle) / 2;
173	            pos[0] = radius * 0.6 * (midangle < Math.PI ? 1 : -1);
174	            return 'translate(' + pos + ')';
175	        })
176	        .style('text-anchor', function(d) {
177	            var midangle = d.startAngle + (d.endAngle - d.startAngle) / 2
178	            return (midangle < Math.PI ? 'start' : 'end')
179	        })
180
181		text.exit()
182			.remove();
183
184		/* ------- SLICE TO TEXT POLYLINES -------*/
185		var polyline = svg.select(".lines").selectAll("polyline")
186			.data(pie(data), key);
187		
188		polyline.enter()
189			.append("polyline");
190
191		polyline.transition().duration(1000)
192			.attrTween("points", function(d){
193				this._current = this._current || d;
194				var interpolate = d3.interpolate(this._current, d);
195				this._current = interpolate(0);
196				return function(t) {
197					var d2 = interpolate(t);
198					var pos = outerArc.centroid(d2);
199					pos[0] = radius * 0.6 * (midAngle(d2) < Math.PI ? 1 : -1);
200					return [arc.centroid(d2), outerArc.centroid(d2), pos];
201				};			
202			});
203		
204		polyline.exit()
205			.remove();
206
207		
208	};
209
210}
211

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.