PageSourceSearch

https://emlc-journal.org/lib/pkp/js/usage-stats-chart.js?v=3.4.0.10

js emlc-journal.org collected 2026-10-02 07:40:37 UTC 4,659 bytes, 187 lines download raw bytes

1/**
2 * @file js/usage-stats-chart.js
3 *
4 * Copyright (c) 2014-2021 Simon Fraser University
5 * Copyright (c) 2000-2021 John Willinsky
6 * Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
7 *
8 * @brief A small handler to initialize Chart.js graphs on the frontend.
9 */
10(function () {
11	/*global pkpUsageStats, Chart */
12
13	if (
14		typeof pkpUsageStats === 'undefined' ||
15		typeof pkpUsageStats.data === 'undefined'
16	) {
17		return;
18	}
19
20	var graphs, noStatsNotice;
21
22	// Check for .querySelectorAll in browser support
23	try {
24		graphs = document.querySelectorAll('.usageStatsGraph');
25		noStatsNotice = document.querySelectorAll('.usageStatsUnavailable');
26	} catch (e) {
27		return;
28	}
29
30	// Hide the unavailable stats notice when a chart is loaded
31	document.addEventListener('usageStatsChartLoaded.pkp', function (e) {
32		for (var i = 0; i < noStatsNotice.length; i++) {
33			if (
34				typeof noStatsNotice[i].dataset.objectType !== 'undefined' &&
35				typeof noStatsNotice[i].dataset.objectId !== 'undefined' &&
36				noStatsNotice[i].dataset.objectType === e.target.dataset.objectType &&
37				noStatsNotice[i].dataset.objectId === e.target.dataset.objectId
38			) {
39				noStatsNotice[i].parentNode.removeChild(noStatsNotice[i]);
40			}
41		}
42	});
43
44	// Define default chart options
45	var chartOptions = {
46		legend: {
47			display: false,
48		},
49		tooltips: {
50			titleFontColor: '#333',
51			bodyFontColor: '#333',
52			footerFontColor: '#333',
53			backgroundColor: '#ddd',
54			cornerRadius: 2,
55		},
56		elements: {
57			line: {
58				borderColor: 'rgba(0,0,0,0.3)',
59				borderWidth: 1,
60				borderJoinStyle: 'round',
61				backgroundColor: 'rgba(0,0,0,0.3)',
62			},
63			rectangle: {
64				backgroundColor: 'rgba(0,0,0,0.3)',
65			},
66			point: {
67				radius: 2,
68				hoverRadius: 6,
69				borderWidth: 0,
70				hitRadius: 5,
71			},
72		},
73		scales: {
74			xAxes: [
75				{
76					gridLines: {
77						color: 'rgba(0,0,0,0.05)',
78						drawTicks: false,
79					},
80				},
81			],
82			yAxes: [
83				{
84					gridLines: {
85						color: 'rgba(0,0,0,0.05)',
86						drawTicks: false,
87					},
88					ticks: {
89						beginAtZero: true
90					}
91				},
92			],
93		},
94	};
95
96	if (pkpUsageStats.config.chartType === 'bar') {
97		chartOptions.scales.xAxes = [
98			{
99				gridLines: {
100					color: 'transparent',
101				},
102			},
103		];
104	}
105
106	// Fire an event to allow third-party customization of the options
107	var optionsEvent = document.createEvent('Event');
108	optionsEvent.initEvent('usageStatsChartOptions.pkp', true, true);
109	optionsEvent.chartOptions = chartOptions;
110	document.dispatchEvent(optionsEvent);
111
112	var graph, objectType, objectId, graphData, initializedEvent;
113	pkpUsageStats.charts = {};
114	for (var g = 0; g < graphs.length; g++) {
115		graph = graphs[g];
116
117		// Check for markup we can use
118		if (
119			typeof graph.dataset.objectType === 'undefined' ||
120			typeof graph.dataset.objectId === 'undefined'
121		) {
122			continue;
123		}
124
125		objectType = graph.dataset.objectType;
126		objectId = graph.dataset.objectId;
127
128		// Check that data exists for this graph
129		if (
130			typeof pkpUsageStats.data[objectType] === 'undefined' ||
131			pkpUsageStats.data[objectType][objectId] === 'undefined'
132		) {
133			continue;
134		}
135
136		// Do nothing if there's no data for this chart
137		if (typeof pkpUsageStats.data[objectType][objectId].data === 'undefined') {
138			graph.parentNode.removeChild(graph);
139			continue;
140		}
141
142		graphData = pkpUsageStats.data[objectType][objectId];
143
144		// Turn the data set into an array
145		var dataArray = [],
146			labelsArray = [],
147			currentDate = new Date(),
148			currentYear = currentDate.getFullYear(),
149			currentMonth = currentDate.getMonth();
150		// Get the data from the last year
151		for (var month = currentMonth + 1; month <= 11; month++) {
152			if (!(currentYear - 1 in graphData.data)) {
153				dataArray.push(0);
154			} else {
155				dataArray.push(graphData.data[currentYear - 1][month + 1]);
156			}
157			labelsArray.push(pkpUsageStats.locale.months[month]);
158		}
159		// Get the data from the current year
160		for (month = 0; month <= currentMonth; month++) {
161			if (!(currentYear in graphData.data)) {
162				dataArray.push(0);
163			} else {
164				dataArray.push(graphData.data[currentYear][month + 1]);
165			}
166			labelsArray.push(pkpUsageStats.locale.months[month]);
167		}
168		pkpUsageStats.charts[objectType + '_' + objectId] = new Chart(graph, {
169			type: pkpUsageStats.config.chartType,
170			data: {
171				labels: labelsArray,
172				datasets: [
173					{
174						label: graphData.label,
175						data: dataArray,
176					},
177				],
178			},
179			options: chartOptions,
180		});
181
182		// Fire an event when the chart is initialized
183		initializedEvent = document.createEvent('Event');
184		initializedEvent.initEvent('usageStatsChartLoaded.pkp', true, true);
185		graph.dispatchEvent(initializedEvent);
186	}
187})();

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.