PageSourceSearch

https://www.satan.lt/Scripts/Charts.js?v=20230224141141

js satan.lt collected 2026-10-03 00:50:49 UTC 12,053 bytes, 369 lines download raw bytes

1Charts = {};
2
3/* Exapmple:
4 <div style="width: 600px;">
5	<canvas class="ChartClass" href="data.csv?X=IQ&Y=GDP&L=Country&TrendType=P&TrendParam=3"></canvas></div>
6*/
7
8Charts.Init = function () {
9	// Find all link elements with the ChartClass class
10	var chartElements = document.querySelectorAll('.ChartClass');
11	// Loop through each link element and add a click event listener
12	for (var i = 0; i < chartElements.length; i++) {
13		var chartElement = chartElements[i];
14		// Get the href attribute of the link element
15		var href = chartElement.getAttribute('data-chart');
16		// Parse the URL parameters from the href attribute
17		var params = new URLSearchParams(href.split('?')[1]);
18		var file = href.split('?')[0];
19		var x = params.get('X');
20		var y = params.get('Y');
21		var l = params.get('L');
22		var trendType = params.get('TrendType');
23		var trendParam = params.get('TrendParam');
24		// Call the CreateChart function with the parsed parameters
25		Charts.NewChart(chartElement, file, x, y, l, trendType, trendParam);
26	}
27}
28
29// Resize the chart canvas when the window is resized
30window.addEventListener('load', function () {
31	// Find all link elements with the ChartClass class
32	var charts = document.querySelectorAll('.ChartClass');
33	// Exist if no charts found on the page.
34	if (charts.length == 0)
35		return;
36	// Load missing cripts.  
37	var scripts = [
38		{ script: "/Scripts/math.js", exists: () => { return typeof polyfit !== "undefined"; } },
39		{ script: "/Scripts/chart.js", exists: () => { return typeof Chart !== "undefined"; } },
40		{ script: "/Scripts/regression.js", exists: () => { return typeof regression !== "undefined"; } },
41		{ script: "/Scripts/d3.v7.min.js", exists: () => { return typeof d3 !== "undefined"; } },
42	];
43	Charts.LoadScripts(
44		scripts,
45		// Initialize charts on success.
46		() => { Charts.Init(); },
47		// Write error message if script loading failed.
48		(s) => { console.log("Error: Load script failed: " + s); })
49});
50
51/** Load required missing JavaScripts scripts */
52Charts.LoadScripts = function LoadScripts(scripts, successCallback, errorCallback) {
53	let remainingScripts = scripts.length;
54	const handleLoad = () => {
55		remainingScripts--;
56		if (remainingScripts === 0)
57			successCallback();
58	};
59	const handleError = (event) => {
60		if (errorCallback)
61			errorCallback(event.target.src);
62	};
63	const findScriptElement = (src) => {
64		const scriptElements = document.getElementsByTagName("script");
65		for (let i = 0; i < scriptElements.length; i++) {
66			if (scriptElements[i].src === src)
67				return scriptElements[i];
68		}
69		return null;
70	};
71	for (let i = 0; i < scripts.length; i++) {
72		const script = scripts[i].script;
73		const exists = scripts[i].exists;
74		if (exists()) {
75			handleLoad();
76			continue;
77		}
78		let scriptElement = findScriptElement(script);
79		if (scriptElement) {
80			scriptElement.addEventListener("load", handleLoad);
81			scriptElement.addEventListener("error", handleError);
82		} else {
83			scriptElement = document.createElement("script");
84			scriptElement.src = script;
85			scriptElement.addEventListener("load", handleLoad);
86			scriptElement.addEventListener("error", handleError);
87			document.head.appendChild(scriptElement);
88		}
89	}
90}
91
92Charts.RoundUpToNearestMultiple = function (numbers) {
93	var maxNumber = Math.max.apply(null, numbers);
94	var minNumber = Math.min.apply(null, numbers);
95	var dif = maxNumber - minNumber;
96	var n = 1;
97	if (dif > 50) n = 10
98	if (dif > 5000) n = 1000
99	return Math.ceil(maxNumber / n) * n;
100}
101
102Charts.RoundDownToNearestMultiple = function (numbers) {
103	var maxNumber = Math.max.apply(null, numbers);
104	var minNumber = Math.min.apply(null, numbers);
105	var dif = maxNumber - minNumber;
106	var n = 1;
107	if (dif > 50) n = 10
108	if (dif > 5000) n = 1000
109	return Math.floor(minNumber / n) * n;
110}
111
112Charts.GetStepSize = function (numbers) {
113	var maxNumber = Math.max.apply(null, numbers);
114	var minNumber = Math.min.apply(null, numbers);
115	var dif = maxNumber - minNumber;
116	if (dif >= 10000) return 1000;
117	if (dif >= 25) return 5;
118	return this.GetStepSizeByTicks(minNumber, maxNumber, 200);
119}
120
121Charts.GetStepSizeByTicks = function(min, max, numTicks) {
122  const range = max - min;
123  const rawStepSize = range / numTicks;
124  const magnitude = Math.floor(Math.log10(rawStepSize));
125  const magnitudeMultiplier = Math.pow(10, magnitude);
126  const normalizedStepSize = Math.ceil(rawStepSize / magnitudeMultiplier) * magnitudeMultiplier;
127  return normalizedStepSize;
128}
129
130Charts.ShowTable = function (data) {
131	// Select the HTML element where you want to display the table
132	var table = d3.select('#table-container').append('table');
133	// Create the table header row and columns
134	var header = table.append('thead').append('tr');
135	header.selectAll('th')
136		.data(Object.keys(data[0]))
137		.enter()
138		.append('th')
139		.text(function (d) { return d; });
140	// Create the table body rows and columns
141	var body = table.append('tbody');
142	var rows = body.selectAll('tr')
143		.data(data)
144		.enter()
145		.append('tr');
146	var cells = rows.selectAll('td')
147		.data(function (row) {
148			return Object.values(row);
149		})
150		.enter()
151		.append('td')
152		.text(function (d) { return d; });
153}
154
155Charts.SortData = function (data, column1, column2, order1, order2) {
156	var order1Multiplier = (order1 == 'asc') ? 1 : -1;
157	var order2Multiplier = (order2 == 'asc') ? 1 : -1;
158	data.sort(function (a, b) {
159		if (a[column1] < b[column1]) {
160			return -1 * order1Multiplier;
161		} else if (a[column1] > b[column1]) {
162			return 1 * order1Multiplier;
163		} else {
164			if (a[column2] < b[column2]) {
165				return -1 * order2Multiplier;
166			} else if (a[column2] > b[column2]) {
167				return 1 * order2Multiplier;
168			} else {
169				return 0;
170			}
171		}
172	});
173	return data;
174}
175
176/** Create new chart. */
177Charts.NewChart = function (element, file, xCol, yCol, lCol, trendType, trentParam) {
178	// Get the data from the CSV file
179	d3.csv(file).then(function (data) {
180		var headers = data.columns.map(function (column) {
181			var newColumn = column.trim();
182			if (newColumn != column) {
183				data.map(function (d) {
184					d[newColumn] = d[column];
185					delete d[column];
186				});
187			}
188			return newColumn;
189		});
190		data.columns = headers;
191		// Extract the values from the data
192		data.map(function (row) {
193			if (typeof row[xCol] == "string")
194				row[xCol] = parseFloat(row[xCol].replace(",", ""));
195			if (typeof row[yCol] == "string")
196				row[yCol] = parseFloat(row[yCol].replace(",", ""));
197		});
198
199		// Remove rows if values failed to parse to a float.
200		data = data.filter(row => {
201			return !isNaN(row[xCol]) && !isNaN(row[yCol]);
202		});
203
204		data = Charts.SortData(data, xCol, 'desc', yCol, 'desc');
205		if (xCol == "EDU") Charts.ShowTable(data);
206
207		// Extract the values from the data
208		var xValues = data.map(function (row) {
209			return parseFloat(row[xCol]);
210		});
211		var yValues = data.map(function (row) {
212			return parseFloat(row[yCol]);
213		});
214
215		var extraLabels = data.map(function (row) { return row[lCol]; });
216		// Add cubic trendline to chart
217		var polynomialData = xValues.map(function (x, i) {
218			return [xValues[i], yValues[i]];
219		});
220		var polynomialOptions = { order: parseInt(trentParam), precision: 6 };
221		var polyfit = regression.polynomial(polynomialData, polynomialOptions);
222		var trendlineDataPol = xValues.map(function (x) {
223			return polyfit.predict(x);
224		});
225		// Define the chart data
226		var chartData = {
227			labels: xValues,
228			datasets: [],
229		};
230		var mainData = {
231			label: lCol,
232			data: yValues,
233			backgroundColor: "rgba(75,192,192,0.8)",
234			borderWidth: 0,
235			borderColor: "rgba(75,192,192,1.0)",
236			pointRadius: 4,
237			pointHoverRadius: 8,
238			pointHoverBackgroundColor: "rgba(75,192,192,0.8)",
239			pointHoverBorderColor: "rgba(75,192,192,1.0)",
240			pointHitRadius: 8,
241			pointHitBackgroundColor: "rgba(75,192,192,0.8)",
242			pointHitBorderColor: "rgba(75,192,192,1.0)",
243			zIndex: 1
244		}
245		// Define the chart options
246		var chartOptions = {
247			layout: {
248				padding: { left: 10, right: 20, top: 10, bottom: 10 }
249			},
250			plugins: {
251				legend: {
252					labels: {
253						filter: function (legendItem, chartData) {
254							//return legendItem.text === lCol; // Show legend for main chart.
255							return false; // Hide all legends.
256						},
257					},
258				},
259				customCanvasBackgroundColor: { color: '#F0F0F0', chartAreaColor: '#FFFFFF' },
260				title: {
261					display: true, text: xCol + " and " + yCol
262				},
263				tooltip: {
264					callbacks: {
265						title: function (context) {
266							return xCol + ": " + xValues[context[0].dataIndex];
267						},
268						label: function (context) {
269							var s = "";
270							s += extraLabels[context.dataIndex];
271							s += " " + yCol + " = " + yValues[context.dataIndex];
272							return s;
273						}
274					}
275				}
276			},
277			scales: {
278				x: {
279					type: 'linear',
280					min: Charts.RoundDownToNearestMultiple(xValues),
281					max: Charts.RoundUpToNearestMultiple(xValues),
282					ticks: { stepSize: Charts.GetStepSize(xValues) },
283					title: { display: true, text: xCol }
284				},
285				y: {
286					type: 'linear',
287					min: Charts.RoundDownToNearestMultiple(yValues),
288					max: Charts.RoundUpToNearestMultiple(yValues),
289					ticks: { stepSize: Charts.GetStepSize(yValues) },
290					title: { display: true, text: yCol }
291				}
292			},
293			onResize: function (chart, size) {
294				chart.data.datasets.forEach((dataset) => {
295					if (dataset.label === lCol) {
296						dataset.pointRadius = size.width / 200;
297						dataset.pointHoverRadius = size.width / 100;
298						dataset.pointHitRadius = size.width / 100;
299					}
300				});
301				chart.update();
302			},
303		};
304
305		if (trendType == "P") {
306		}
307		var trendlinePol = {
308			label: 'Trendline: ' + polyfit.string,
309			backgroundColor: "rgba(255,255,255,0)",
310			borderColor: "rgba(255,0,0,1)",
311			borderWidth: 2,
312			data: trendlineDataPol,
313			pointRadius: 0,
314			showLine: true,
315			zIndex: 10,
316		};
317		// Push trendline on top.
318		chartData.datasets.push(trendlinePol);
319		// Push main data.
320		chartData.datasets.push(mainData);
321		// Get the canvas element and create the chart
322		var ctx = element.getContext('2d');
323		var chart = new Chart(ctx, {
324			type: 'line',
325			data: chartData,
326			options: chartOptions,
327			plugins: [SetChartAreaBackgroundPlugin],
328		});
329		var textCanvas = document.createElement('canvas');
330		textCanvas.width = element.width;
331		textCanvas.height = element.height;
332		textCanvas.style.position = 'absolute';
333		textCanvas.style.left = element.offsetLeft + 'px';
334		textCanvas.style.top = element.offsetTop + 'px';
335		textCanvas.style.zIndex = 2;
336		chart.update();
337		// Resize the chart canvas when the window is resized
338		window.addEventListener('resize', function () {
339			chart.resize();
340		});
341	});
342
343	// Note: changes to the plugin code is not reflected to the chart, because the plugin is loaded at chart construction time and editor changes only trigger an chart.update().
344	const SetChartAreaBackgroundPlugin = {
345		id: 'customCanvasBackgroundColor',
346		beforeDraw: (chart, args, options) => {
347			const { ctx } = chart;
348			const chartArea = chart.chartArea;
349			ctx.save();
350			ctx.globalCompositeOperation = 'destination-over';
351			if (options.color) {
352				ctx.fillStyle = options.color;
353				//ctx.fillRect(0, 0, chart.width, chart.height);
354				ctx.fillRect(0, 0, chart.width, chartArea.top);
355				ctx.fillRect(0, chartArea.top, chartArea.left, chartArea.bottom - chartArea.top);
356				ctx.fillRect(chartArea.left + chartArea.width, chartArea.top, chart.width - chartArea.left - chartArea.width, chartArea.height);
357				ctx.fillRect(0, chartArea.top + chartArea.height, chart.width, chart.height - chartArea.top - chartArea.height);
358			}
359			if (options.chartAreaColor) {
360				ctx.fillStyle = options.chartAreaColor;
361				ctx.fillRect(chartArea.left, chartArea.top, chartArea.right - chartArea.left, chartArea.bottom - chartArea.top);
362			}
363			ctx.restore();
364		}
365	};
366
367}
368
369

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.