MediaWiki:Gadget-Charts-core.js

From Old School Near-Reality Wiki
Jump to navigation Jump to search

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Press Ctrl-F5.
  1 var DARKMODE_TEXT = '#cbd9f4';
  2 
  3 function RSWChart(i, dataElement) {
  4     var self = this;
  5     this.is_error = false;
  6     this.index = i;
  7 
  8     function error(t) {
  9         dataElement.removeClass('rsw-chartjs-config').addClass("rsw-chart-parsed rsw-chart-error").text(t);
 10         self.is_error = true;
 11     }
 12 
 13     function parseData() {
 14         console.log('parsing data for ' + self.index);
 15         if (self.is_error) return;
 16         var c = {};
 17         console.log(dataElement.text());
 18         try {
 19             var txt = dataElement.text();
 20             txt = txt.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/=/g, '&equals;').replace(/\\/g, '&bsol;').replace(/\//g, '&sol;');
 21             return JSON.parse(txt);
 22         } catch (e) {
 23             error("Failed to parse JSON. " + e.name + ": " + e.message);
 24         }
 25     }
 26 
 27     function addFunctions() {
 28         var opts = self.config.options;
 29         if (opts.tooltips.format == "skillingSuccess") {
 30             opts.tooltips.callbacks = opts.tooltips.callbacks || {}
 31             opts.tooltips.callbacks.label = function(tooltipItem) {
 32                 var label = tooltipItem.dataset.label.trim() || '';
 33                 if (label) {
 34                     label += ': ';
 35                 }
 36                 label += "Level: " + tooltipItem.label + "; Chance: ";
 37                 label += (tooltipItem.dataPoint.y * 100).toFixed(2) + "%";
 38                 return label;
 39             }
 40         }
 41 
 42         if (opts.scales.y.ticks.format == "percent") {
 43             opts.scales.y.ticks.callback = function(value) {
 44                 return Math.round(value * 100) + "%"
 45             }
 46         }
 47 
 48         opts.datasetsPerGroup = opts.datasetsPerGroup || 1;
 49         if (opts.datasetsPerGroup !== 1) {
 50             opts.tooltips.filter = function(tooltipItem) {
 51                 return tooltipItem.datasetIndex % opts.datasetsPerGroup == 0 || tooltipItem.dataIndex > 0;
 52             }
 53 
 54             opts.legend = opts.legend || {};
 55             opts.legend.labels = opts.legend.labels || {};
 56             opts.legend.labels.filter = function(legendItem, data) {
 57                 return legendItem.datasetIndex % 3 == 0;
 58             }
 59 
 60             opts.legend.onClick = function(e, legendItem) {
 61                 var index = legendItem.datasetIndex;
 62 
 63                 var ci = this.chart;
 64                 [
 65                     ci.getDatasetMeta(index - index % 3 + 0),
 66                     ci.getDatasetMeta(index - index % 3 + 1),
 67                     ci.getDatasetMeta(index - index % 3 + 2)
 68                 ].forEach(function(meta) {
 69                     meta.hidden = meta.hidden === null ? !ci.data.datasets[index].hidden : null;
 70                 });
 71                 ci.update();
 72             };
 73         }
 74 
 75         var legendIconWidth = 25;
 76         var legendIconHeight = 25;
 77         var legendIconBorder = 2;
 78         self.config.data.datasets.forEach(function(dataset, i) {
 79             if (i % opts.datasetsPerGroup == 0 && dataset.pointStyleImg !== undefined) {
 80                 opts.legend = opts.legend || {};
 81                 opts.legend.labels = opts.legend.labels || {};
 82                 opts.legend.labels.usePointStyle = true;
 83                 opts.legend.labels.font = opts.legend.labels.font || {};
 84                 opts.legend.labels.font.size = 14;
 85                 var baseColor = dataset.baseColor || dataset.borderColor;
 86                 var canvas = document.createElement("canvas")
 87                 canvas.width = legendIconWidth;
 88                 canvas.height = legendIconHeight;
 89                 var myctx = canvas.getContext("2d");
 90                 myctx.fillStyle = baseColor;
 91                 myctx.fillRect(0, 0, canvas.width, canvas.height);
 92                 myctx.fillStyle = "white";
 93                 myctx.fillRect(legendIconBorder, legendIconBorder, canvas.width - 2 * legendIconBorder, canvas.height - 2 * legendIconBorder);
 94                 var colorData = myctx.getImageData(0, 0, 1, 1).data;
 95                 var translColor = "rgba(" + colorData[0] + ", " + colorData[1] + ", " + colorData[2] + ", 0.15)";
 96                 myctx.fillStyle = translColor;
 97                 myctx.fillRect(0, 0, canvas.width, canvas.height);
 98                 var image = new Image()
 99                 image.src = rs.getFileURLCached(dataset.pointStyleImg);
100                 image.crossOrigin = "anonymous"
101                 image.onload = function() {
102                     var imgSize = legendIconWidth - legendIconBorder * 2;
103                     var imgScale = Math.min(1.0, imgSize/image.width, imgSize/image.height);
104                     var imgWidth = imgScale * image.width;
105                     var imgHeight = imgScale * image.height
106                     myctx.drawImage(image, (legendIconWidth - imgWidth)/2, (legendIconHeight - imgHeight)/2, imgWidth, imgHeight);
107                 }
108                 dataset.pointStyle = canvas;
109 
110                 for (var j = 0; j < opts.datasetsPerGroup; j++) {
111                     self.config.data.datasets[i + j].borderColor = baseColor;
112                     self.config.data.datasets[i + j].backgroundColor = translColor;
113                     self.config.data.datasets[i + j].hoverBorderColor = baseColor;
114                     self.config.data.datasets[i + j].hoverBackgroundColor = translColor;
115                     self.config.data.datasets[i + j].hoverRadius = 0;
116                     if (j == 0) {
117                         self.config.data.datasets[i+j].borderColor = translColor;
118                         self.config.data.datasets[i+j].hoverBorderColor = translColor;
119                     }
120                 }
121             }
122         })
123     }
124 
125     function makeChart() {
126         console.log('making chart for ' + self.index);
127         if (self.is_error) return;
128 
129         var canvas = $('<canvas class="rsw-chartjs-canvas">');
130         canvas.attr('id', 'rsw-chartjs-chart-' + self.index);
131         dataElement.empty().append(canvas).removeClass('rsw-chartjs-config').addClass("rsw-chart-parsed");
132         self.chart = new Chart(canvas, self.config);
133     }
134     this.config = parseData();
135     addFunctions()
136     makeChart();
137     self.chart.update();
138 }
139 
140 function init() {
141     console.log('chart init');
142     // force all text to be darkmode happy by default
143     // if ($('.skin-vector.wgl-darkmode').length) {
144     //     Chart.defaults.font.color = DARKMODE_TEXT;
145     //     Chart.defaults.color = 'rgba(255,255,255,0.1)';
146     //     Chart.defaults.scale.gridLines.color = 'rgba(255,255,255,0.1)';
147     // }
148     //other defaults
149     Chart.defaults.plugins['legend'].labels.usePointStyle = true;
150 
151     window.charts = [];
152     $('.rsw-chartjs-config').each(function(i, e) {
153         console.log('creating chart ' + i);
154         window.charts.push(new RSWChart(i, $(e)));
155     });
156     window.RSWChart = RSWChart;
157 }
158 
159 function addHook() {
160     mw.hook('rscalc.submit').add(init);
161     if (!window.charts) {
162         init();
163     }
164 }
165 
166 $.when($.ready, $.getScript("https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.0.0-beta/chart.min.js")).then(addHook, function() {
167     console.error("Failed to load chart.js");
168 });