/**
* @file js/usage-stats-chart.js
*
* Copyright (c) 2014-2021 Simon Fraser University
* Copyright (c) 2000-2021 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @brief A small handler to initialize Chart.js graphs on the frontend.
*/
(function () {
/*global pkpUsageStats, Chart */
if (
typeof pkpUsageStats === 'undefined' ||
typeof pkpUsageStats.data === 'undefined'
) {
return;
}
var graphs, noStatsNotice;
// Check for .querySelectorAll in browser support
try {
graphs = document.querySelectorAll('.usageStatsGraph');
noStatsNotice = document.querySelectorAll('.usageStatsUnavailable');
} catch (e) {
return;
}
// Hide the unavailable stats notice when a chart is loaded
document.addEventListener('usageStatsChartLoaded.pkp', function (e) {
for (var i = 0; i < noStatsNotice.length; i++) {
if (
typeof noStatsNotice[i].dataset.objectType !== 'undefined' &&
typeof noStatsNotice[i].dataset.objectId !== 'undefined' &&
noStatsNotice[i].dataset.objectType === e.target.dataset.objectType &&
noStatsNotice[i].dataset.objectId === e.target.dataset.objectId
) {
noStatsNotice[i].parentNode.removeChild(noStatsNotice[i]);
}
}
});
// Define default chart options
var chartOptions = {
legend: {
display: false,
},
tooltips: {
titleColor: '#333',
bodyColor: '#333',
footerColor: '#333',
backgroundColor: '#ddd',
cornerRadius: 2,
},
elements: {
line: {
borderColor: 'rgba(0,0,0,0.3)',
borderWidth: 1,
borderJoinStyle: 'round',
backgroundColor: 'rgba(0,0,0,0.3)',
},
rectangle: {
backgroundColor: 'rgba(0,0,0,0.3)',
},
point: {
radius: 2,
hoverRadius: 6,
borderWidth: 0,
hitRadius: 5,
},
},
scales: {
xAxes: [
{
gridLines: {
color: 'rgba(0,0,0,0.05)',
drawTicks: false,
},
},
],
yAxes: [
{
gridLines: {
color: 'rgba(0,0,0,0.05)',
drawTicks: false,
},
},
],
},
};
if (pkpUsageStats.config.chartType === 'bar') {
chartOptions.scales.xAxes = [
{
gridLines: {
color: 'transparent',
},
},
];
}
// Fire an event to allow third-party customization of the options
var optionsEvent = document.createEvent('Event');
optionsEvent.initEvent('usageStatsChartOptions.pkp', true, true);
optionsEvent.chartOptions = chartOptions;
document.dispatchEvent(optionsEvent);
var graph, objectType, objectId, graphData, initializedEvent;
pkpUsageStats.charts = {};
for (var g = 0; g < graphs.length; g++) {
graph = graphs[g];
// Check for markup we can use
if (
typeof graph.dataset.objectType === 'undefined' ||
typeof graph.dataset.objectId === 'undefined'
) {
continue;
}
objectType = graph.dataset.objectType;
objectId = graph.dataset.objectId;
// Check that data exists for this graph
if (
typeof pkpUsageStats.data[objectType] === 'undefined' ||
pkpUsageStats.data[objectType][objectId] === 'undefined'
) {
continue;
}
// Do nothing if there's no data for this chart
if (typeof pkpUsageStats.data[objectType][objectId].data === 'undefined') {
graph.parentNode.removeChild(graph);
continue;
}
graphData = pkpUsageStats.data[objectType][objectId];
// Turn the data set into an array
var dataArray = [],
labelsArray = [],
currentDate = new Date(),
currentYear = currentDate.getFullYear(),
currentMonth = currentDate.getMonth();
// Get the data from the last year
for (var month = currentMonth + 1; month <= 11; month++) {
if (!(currentYear - 1 in graphData.data)) {
dataArray.push(0);
} else {
dataArray.push(graphData.data[currentYear - 1][month + 1]);
}
labelsArray.push(pkpUsageStats.locale.months[month]);
}
// Get the data from the current year
for (month = 0; month <= currentMonth; month++) {
if (!(currentYear in graphData.data)) {
dataArray.push(0);
} else {
dataArray.push(graphData.data[currentYear][month + 1]);
}
labelsArray.push(pkpUsageStats.locale.months[month]);
}
pkpUsageStats.charts[objectType + '_' + objectId] = new Chart(graph, {
type: pkpUsageStats.config.chartType,
data: {
labels: labelsArray,
datasets: [
{
label: graphData.label,
data: dataArray,
},
],
},
options: chartOptions,
});
// Fire an event when the chart is initialized
initializedEvent = document.createEvent('Event');
initializedEvent.initEvent('usageStatsChartLoaded.pkp', true, true);
graph.dispatchEvent(initializedEvent);
}
})();