PageSourceSearch

https://www.amnesty.it/public/themes/amnesty/javascripts/mapJustice.js

js amnesty.it collected 2026-09-24 08:50:27 UTC 5,088 bytes, 180 lines download raw bytes

1(function (root, factory) {
2	if (typeof define === 'function' && define.amd) {
3		// AMD. Register as an anonymous module.
4		define(['d3', 'topojson'], factory);
5	} else if (typeof exports === 'object') {
6		// Node. Does not work with strict CommonJS, but
7		// only CommonJS-like environments that support module.exports,
8		// like Node.
9		module.exports = factory(require('d3'), require('topojson'));
10	} else {
11		// Browser globals (root is window)
12		root.mapJustice = factory(d3, topojson);
13	}
14}(this, function (d3, topojson) {
15	'use strict';
16
17	// colors
18	var landGray = '#C4CBCE';
19	var countryR = 255;
20	var countryG = 255;
21	var countryB = 0;
22
23	var scale = 3;
24	var width, height,
25		land, countries,
26		context, canvas,
27		projection, translateY, path,
28		oldCountry;
29	var onReadyHighlight;
30
31	var mapJustice = {
32		ready: false,
33		reInit: function(container, newCountryCode) {
34			// If the container is not an Element terminate early
35			if (!container.tagName) {
36				console && console.error(
37					'[mapJustice] `container` is not an Element. `container`:',
38					container
39				);
40				return;
41			}
42
43			var canvas = d3.select(container).select('canvas');
44			if (canvas) canvas.remove();
45
46			this.init(container, newCountryCode);
47		},
48		init: function(container, newCountryCode) {
49			// If the container is not an Element terminate early
50			if (!container.tagName) {
51				console && console.error(
52					'[mapJustice] `container` is not an Element. `container`:',
53					container
54				);
55				return;
56			}
57
58			width  = container.clientWidth;
59			height = container.clientHeight + 150; // +150 Because of the long text loaded later
60
61			translateY = height / 2;
62			projection = d3.geoEquirectangular()
63				.translate([width * 0.8, translateY])
64				.scale(width / scale);
65
66			canvas = d3.select(container).append('canvas')
67				.attr('width', width)
68				.attr('height', height);
69
70			context = canvas.node().getContext('2d');
71
72			path = d3.geoPath(projection, context);
73
74			d3.queue()
75				.defer(d3.json, '/public/themes/amnesty/javascripts/world-110m.json')
76				.defer(d3.json, '/public/themes/amnesty/javascripts/world-110m-country-codes.json')
77				.await(ready.bind(this));
78
79			function ready(error, world, names) {
80				if (error) {
81					console && console.error(
82						'[mapJustice] Error getting data:',
83						error
84					);
85					return;
86				}
87
88				land = topojson.feature(world, world.objects.land);
89				countries = topojson.feature(world, world.objects.countries).features;
90
91				// Merge topojson earth with country codes
92				countries = countries.filter(function(d) {
93					return names.some(function(n) {
94						if (d.id == n.id) return d.code = n.code;
95					});
96				}).sort(function(a, b) {
97					return a.code.localeCompare(b.code);
98				});
99
100				this.ready = true;
101				var highlight = onReadyHighlight ? onReadyHighlight : newCountryCode;
102				this.highlight(highlight);
103
104			};
105		},
106		highlight: function(newCountryCode) {
107			if (!this.ready) {
108				onReadyHighlight = newCountryCode;
109				return;
110			}
111
112			newCountryCode = newCountryCode ? newCountryCode : '';
113			var newCountry;
114
115			for (var k = countries.length - 1; k >= 0; k--) {
116				if (countries[k].code.toLowerCase() === newCountryCode.toLowerCase()) {
117					newCountry = countries[k];
118				}
119			}
120
121			d3.transition()
122				.duration(1000)
123				.ease(d3.easePolyOut.exponent(5))
124				.tween('trans', function() {
125					// get the top-left-most point of the country
126					var centroid = newCountry ? d3.geoCentroid(newCountry) : [0, 0];
127
128					// limit the maximum Y offset so we don't show beyond the poles
129					if (centroid[1] > 43) centroid[1] = 43;
130					else if (centroid[1] < -43) centroid[1] = -43;
131
132					var pxCentroid = projection(centroid);
133
134					var rotationX = d3.interpolateNumber(projection.rotate()[0], -centroid[0]);
135					var translationY = d3.interpolateNumber(projection.translate()[1],
136						projection.translate()[1] - pxCentroid[1] + translateY);
137
138					// https://github.com/d3/d3-interpolate#interpolateNumber
139					// 1e-6 is the smallest value that is not stringified in scientific notation
140					var newOpacity = d3.interpolateNumber(1e-6, 1);
141					var oldOpacity = d3.interpolateNumber(1, 1e-6);
142
143					return function(t) {
144						projection.rotate([rotationX(t), 0, 0]);
145						projection.translate([projection.translate()[0], translationY(t)]);
146
147						context.clearRect(0, 0, width, height);
148
149						// land
150						context.beginPath();
151						path(land);
152						context.fillStyle = landGray;
153						context.fill();
154
155						// fade out old country
156						if (oldCountry) {
157							context.beginPath();
158							path(oldCountry);
159							context.fillStyle = 'rgba(' + countryR + ',' + countryG + ',' + countryB + ',' + oldOpacity(Math.sqrt(t)) + ')';
160							context.fill();
161						}
162
163						// fade in new country
164						if (newCountry) {
165							context.beginPath();
166							path(newCountry);
167							context.fillStyle = 'rgba(' + countryR + ',' + countryG + ',' + countryB + ',' + newOpacity(t) + ')';
168							context.fill();
169						}
170					};
171				})
172				.on('end', function() {
173					oldCountry = newCountry;
174				});
175
176		}
177	};
178
179	return mapJustice;
180}));

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.