PageSourceSearch

https://www.generali-investments.si/wp-content/themes/enfold-child…/chartjs-plugin-labels.js?x47102&ver=1.1.0

js generali-investments.si collected 2026-10-08 06:22:22 UTC 15,981 bytes, 490 lines download raw bytes

vendor: 15,981 bytes, lines 1-490
1/**
2 * [chartjs-plugin-labels]{@link https://github.com/emn178/chartjs-plugin-labels}
3 *
4 * @version 1.1.0
5 * @author Chen, Yi-Cyuan [[email protected]]
6 * @copyright Chen, Yi-Cyuan 2017-2018
7 * @license MIT
8 */
9(function () {
10  'use strict';
11
12  if (typeof Chart === 'undefined') {
13    console.error('Can not find Chart object.');
14    return;
15  }
16
17  if (typeof Object.assign != 'function') {
18    Object.assign = function (target, varArgs) {
19      if (target == null) {
20        throw new TypeError('Cannot convert undefined or null to object');
21      }
22      var to = Object(target);
23      for (var index = 1; index < arguments.length; index++) {
24        var nextSource = arguments[index];
25        if (nextSource != null) {
26          for (var nextKey in nextSource) {
27            if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
28              to[nextKey] = nextSource[nextKey];
29            }
30          }
31        }
32      }
33      return to;
34    };
35  }
36
37  var SUPPORTED_TYPES = {};
38  ['pie', 'doughnut', 'polarArea', 'bar'].forEach(function (t) {
39    SUPPORTED_TYPES[t] = true;
40  });
41
42  function Label() {
43    this.renderToDataset = this.renderToDataset.bind(this);
44  }
45
46  Label.prototype.setup = function (chart, options) {
47    this.chart = chart;
48    this.ctx = chart.ctx;
49    this.args = {};
50    this.barTotal = {};
51    var chartOptions = chart.config.options;
52    this.options = Object.assign({
53      position: 'default',
54      precision: 0,
55      fontSize: chartOptions.defaultFontSize,
56      fontColor: chartOptions.defaultFontColor,
57      fontStyle: chartOptions.defaultFontStyle,
58      fontFamily: chartOptions.defaultFontFamily,
59      shadowOffsetX: 3,
60      shadowOffsetY: 3,
61      shadowColor: 'rgba(0,0,0,0.3)',
62      shadowBlur: 6,
63      images: [],
64      outsidePadding: 2,
65      textMargin: 2,
66      overlap: true
67    }, options);
68    if (chart.config.type === 'bar') {
69      this.options.position = 'default';
70      this.options.arc = false;
71      this.options.overlap = true;
72    }
73  };
74
75  Label.prototype.render = function () {
76    this.labelBounds = [];
77    this.chart.data.datasets.forEach(this.renderToDataset);
78  };
79
80  Label.prototype.renderToDataset = function (dataset, index) {
81    this.totalPercentage = 0;
82    this.total = null;
83    var arg = this.args[index];
84    arg.meta.data.forEach(function (element, index) {
85      this.renderToElement(dataset, arg, element, index);
86    }.bind(this));
87  };
88
89  Label.prototype.renderToElement = function (dataset, arg, element, index) {
90    if (!this.shouldRenderToElement(arg.meta, element)) {
91      return;
92    }
93    this.percentage = null;
94    var label = this.getLabel(dataset, element, index);
95    if (!label) {
96      return;
97    }
98    var ctx = this.ctx;
99    ctx.save();
100    ctx.font = Chart.helpers.fontString(this.options.fontSize, this.options.fontStyle, this.options.fontFamily);
101    var renderInfo = this.getRenderInfo(element, label);
102    if (!this.drawable(element, label, renderInfo)) {
103      ctx.restore();
104      return;
105    }
106    ctx.beginPath();
107    ctx.fillStyle = this.getFontColor(dataset, element, index);
108    this.renderLabel(label, renderInfo);
109    ctx.restore();
110  };
111
112  Label.prototype.renderLabel = function (label, renderInfo) {
113    return this.options.arc ? this.renderArcLabel(label, renderInfo) : this.renderBaseLabel(label, renderInfo);
114  };
115
116  Label.prototype.renderBaseLabel = function (label, position) {
117    var ctx = this.ctx;
118    if (typeof label === 'object') {
119      ctx.drawImage(label, position.x - label.width / 2, position.y - label.height / 2, label.width, label.height);
120    } else {
121      ctx.save();
122      ctx.textBaseline = 'top';
123      ctx.textAlign = 'center';
124
125      if (this.options.textShadow) {
126        ctx.shadowOffsetX = this.options.shadowOffsetX;
127        ctx.shadowOffsetY = this.options.shadowOffsetY;
128        ctx.shadowColor = this.options.shadowColor;
129        ctx.shadowBlur = this.options.shadowBlur;
130      }
131
132      var lines = label.split('\n');
133      for (var i = 0; i < lines.length; i++) {
134        var y = position.y - this.options.fontSize / 2 * lines.length + this.options.fontSize * i;
135        ctx.fillText(lines[i], position.x, y);
136      }
137      ctx.restore();
138    }
139  };
140
141  Label.prototype.renderArcLabel = function (label, renderInfo) {
142    var ctx = this.ctx, radius = renderInfo.radius, view = renderInfo.view;
143    ctx.save();
144    ctx.translate(view.x, view.y);
145    if (typeof label === 'string') {
146      ctx.rotate(renderInfo.startAngle);
147      ctx.textBaseline = 'middle';
148      ctx.textAlign = 'left';
149      var lines = label.split('\n'), max = 0, widths = [], offset = 0;
150      if (this.options.position === 'border') {
151        offset = (lines.length - 1) * this.options.fontSize / 2;
152      }
153      for (var j = 0; j < lines.length; ++j) {
154        var mertrics = ctx.measureText(lines[j]);
155        if (mertrics.width > max) {
156          max = mertrics.width;
157        }
158        widths.push(mertrics.width);
159      }
160      for (var j = 0; j < lines.length; ++j) {
161        var line = lines[j];
162        var y = (lines.length - 1 - j) * -this.options.fontSize + offset;
163        ctx.save();
164        var padding = (max - widths[j]) / 2;
165        ctx.rotate(padding / radius);
166        for (var i = 0; i < line.length; i++) {
167          var char = line.charAt(i);
168          mertrics = ctx.measureText(char);
169          ctx.save();
170          ctx.translate(0, -1 * radius);
171          ctx.fillText(char, 0, y);
172          ctx.restore();
173          ctx.rotate(mertrics.width / radius);
174        }
175        ctx.restore();
176      }
177    } else {
178      ctx.rotate((view.startAngle + Math.PI / 2 + renderInfo.endAngle) / 2);
179      ctx.translate(0, -1 * radius);
180      this.renderLabel(label, { x: 0, y: 0 });
181    }
182    ctx.restore();
183  };
184
185  Label.prototype.shouldRenderToElement = function (meta, element) {
186    return !meta.hidden && !element.hidden && (
187      this.options.showZero ||
188      this.chart.config.type === 'polarArea' ? element._view.outerRadius !== 0 : element._view.circumference !== 0
189    );
190  };
191
192  Label.prototype.getLabel = function (dataset, element, index) {
193    var label;
194    if (typeof this.options.render === 'function') {
195      label = this.options.render({
196        label: this.chart.config.data.labels[index],
197        value: dataset.data[index],
198        percentage: this.getPercentage(dataset, element, index),
199        dataset: dataset,
200        index: index
201      });
202    } else {
203      switch (this.options.render) {
204        case 'value':
205          label = dataset.data[index];
206          break;
207        case 'label':
208          label = this.chart.config.data.labels[index];
209          break;
210        case 'image':
211          label = this.options.images[index] ? this.loadImage(this.options.images[index]) : '';
212          break;
213        case 'percentage':
214        default:
215          label = this.getPercentage(dataset, element, index) + '%';
216          break;
217      }
218    }
219    if (typeof label === 'object') {
220      label = this.loadImage(label);
221    } else if (label !== null && label !== undefined) {
222      label = label.toString();
223    }
224    return label;
225  };
226
227  Label.prototype.getFontColor = function (dataset, element, index) {
228    var fontColor = this.options.fontColor;
229    if (typeof fontColor === 'function') {
230      fontColor = fontColor({
231        label: this.chart.config.data.labels[index],
232        value: dataset.data[index],
233        percentage: this.getPercentage(dataset, element, index),
234        backgroundColor: dataset.backgroundColor[index],
235        dataset: dataset,
236        index: index
237      });
238    } else if (typeof fontColor !== 'string') {
239      fontColor = fontColor[index] || this.chart.config.options.defaultFontColor;
240    }
241    return fontColor;
242  };
243
244  Label.prototype.getPercentage = function (dataset, element, index) {
245    if (this.percentage !== null) {
246      return this.percentage;
247    }
248    var percentage;
249    if (this.chart.config.type === 'polarArea') {
250      if (this.total === null) {
251        this.total = 0;
252        for (var i = 0;i < dataset.data.length; ++i) {
253          this.total += dataset.data[i];
254        }
255      }
256      percentage = dataset.data[index] / this.total * 100;
257    } else if (this.chart.config.type === 'bar') {
258      if (this.barTotal[index] === undefined) {
259        this.barTotal[index] = 0;
260        for (var i = 0;i < this.chart.data.datasets.length; ++i) {
261          this.barTotal[index] += this.chart.data.datasets[i].data[index];
262        }
263      }
264      percentage = dataset.data[index] / this.barTotal[index] * 100;
265    } else {
266      percentage = element._view.circumference / this.chart.config.options.circumference * 100;
267    }
268    percentage = parseFloat(percentage.toFixed(this.options.precision));
269    if (!this.options.showActualPercentages) {
270      if (this.chart.config.type === 'bar') {
271        this.totalPercentage = this.barTotalPercentage[index] || 0;
272      }
273      this.totalPercentage += percentage;
274      if (this.totalPercentage > 100) {
275        percentage -= this.totalPercentage - 100;
276        percentage = parseFloat(percentage.toFixed(this.options.precision));
277      }
278      if (this.chart.config.type === 'bar') {
279        this.barTotalPercentage[index] = this.totalPercentage
280      }
281    }
282    this.percentage = percentage;
283    return percentage;
284  };
285
286  Label.prototype.getRenderInfo = function (element, label) {
287    if (this.chart.config.type === 'bar') {
288      return this.getBarRenderInfo(element, label);
289    } else {
290      return this.options.arc ? this.getArcRenderInfo(element, label) : this.getBaseRenderInfo(element, label);
291    }
292  };
293
294  Label.prototype.getBaseRenderInfo = function (element, label) {
295    if (this.options.position === 'outside' || this.options.position === 'border') {
296      var renderInfo, rangeFromCentre,
297        view = element._view,
298        centreAngle = view.startAngle + (view.endAngle - view.startAngle) / 2,
299        innerRadius = view.outerRadius / 2;
300      if (this.options.position === 'border') {
301        rangeFromCentre = (view.outerRadius - innerRadius) / 2 + innerRadius;
302      } else if (this.options.position === 'outside') {
303        rangeFromCentre = (view.outerRadius - innerRadius) + innerRadius + this.options.textMargin;
304      }
305      renderInfo = {
306        x: view.x + (Math.cos(centreAngle) * rangeFromCentre),
307        y: view.y + (Math.sin(centreAngle) * rangeFromCentre)
308      };
309      if (this.options.position === 'outside') {
310        var offset = this.options.textMargin + this.measureLabel(label).width / 2;
311        renderInfo.x += renderInfo.x < view.x ? -offset : offset;
312      }
313      return renderInfo;
314    } else {
315      return element.tooltipPosition();
316    }
317  };
318
319  Label.prototype.getArcRenderInfo = function (element, label) {
320    var radius, view = element._view;
321    if (this.options.position === 'outside') {
322      radius = view.outerRadius + this.options.fontSize + this.options.textMargin;
323    } else if (this.options.position === 'border') {
324      radius = (view.outerRadius / 2 + view.outerRadius) / 2;
325    } else {
326      radius = (view.innerRadius + view.outerRadius) / 2;
327    }
328    var startAngle = view.startAngle, endAngle = view.endAngle;
329    var totalAngle = endAngle - startAngle;
330    startAngle += Math.PI / 2;
331    endAngle += Math.PI / 2;
332    var mertrics = this.measureLabel(label);
333    startAngle += (endAngle - (mertrics.width / radius + startAngle)) / 2;
334    return {
335      radius: radius,
336      startAngle: startAngle,
337      endAngle: endAngle,
338      totalAngle: totalAngle,
339      view: view
340    }
341  };
342
343  Label.prototype.getBarRenderInfo = function (element, label) {
344    var renderInfo = element.tooltipPosition();
345    renderInfo.y -= this.measureLabel(label).height / 2 + this.options.textMargin;
346    return renderInfo;
347  };
348
349  Label.prototype.drawable = function (element, label, renderInfo) {
350    if (this.options.overlap) {
351      return true;
352    } else if (this.options.arc) {
353      return renderInfo.endAngle - renderInfo.startAngle <= renderInfo.totalAngle;
354    } else {
355      var mertrics = this.measureLabel(label),
356        left = renderInfo.x - mertrics.width / 2,
357        right = renderInfo.x + mertrics.width / 2,
358        top = renderInfo.y - mertrics.height / 2,
359        bottom = renderInfo.y + mertrics.height / 2;
360      if (this.options.renderInfo === 'outside') {
361        return this.outsideInRange(left, right, top, bottom);
362      } else {
363        return element.inRange(left, top) && element.inRange(left, bottom) &&
364          element.inRange(right, top) && element.inRange(right, bottom);
365      }
366    }
367  };
368
369  Label.prototype.outsideInRange = function (left, right, top, bottom) {
370    var labelBounds = this.labelBounds;
371    for (var i = 0;i < labelBounds.length;++i) {
372      var bound = labelBounds[i];
373      var potins = [
374        [left, top],
375        [left, bottom],
376        [right, top],
377        [right, bottom]
378      ];
379      for (var j = 0;j < potins.length;++j) {
380        var x = potins[j][0];
381        var y = potins[j][1];
382        if (x >= bound.left && x <= bound.right && y >= bound.top && y <= bound.bottom) {
383          return false;
384        }
385      }
386      potins = [
387        [bound.left, bound.top],
388        [bound.left, bound.bottom],
389        [bound.right, bound.top],
390        [bound.right, bound.bottom]
391      ];
392      for (var j = 0;j < potins.length;++j) {
393        var x = potins[j][0];
394        var y = potins[j][1];
395        if (x >= left && x <= right && y >= top && y <= bottom) {
396          return false;
397        }
398      }
399    }
400    labelBounds.push({
401      left: left,
402      right: right,
403      top: top,
404      bottom: bottom
405    });
406    return true;
407  };
408
409  Label.prototype.measureLabel = function (label) {
410    if (typeof label === 'object') {
411      return { width: label.width, height: label.height };
412    } else {
413      var width = 0;
414      var lines = label.split('\n');
415      for (var i = 0; i < lines.length; ++i) {
416        var result = this.ctx.measureText(lines[i]);
417        if (result.width > width) {
418          width = result.width;
419        }
420      }
421      return { width: width, height: this.options.fontSize * lines.length };
422    }
423  };
424
425  Label.prototype.loadImage = function (obj) {
426    var image = new Image();
427    image.src = obj.src;
428    image.width = obj.width;
429    image.height = obj.height;
430    return image;
431  };
432
433  Chart.plugins.register({
434    id: 'labels',
435    beforeDatasetsUpdate: function (chart, options) {
436      if (!SUPPORTED_TYPES[chart.config.type]) {
437        return;
438      }
439      if (!Array.isArray(options)) {
440        options = [options];
441      }
442      var count = options.length;
443      if (!chart._labels || count !== chart._labels.length) {
444        chart._labels = options.map(function () {
445          return new Label();
446        });
447      }
448      var someOutside = false, maxPadding = 0;
449      for (var i = 0; i < count; ++i) {
450        var label = chart._labels[i];
451        label.setup(chart, options[i]);
452        if (label.options.position === 'outside') {
453          someOutside = true;
454          var padding = label.options.fontSize * 1.5 + label.options.outsidePadding;
455          if (padding > maxPadding) {
456            maxPadding = padding;
457          }
458        }
459      }
460      if (someOutside) {
461        chart.chartArea.top += maxPadding;
462        chart.chartArea.bottom -= maxPadding;
463      }
464    },
465    afterDatasetUpdate: function (chart, args, options) {
466      if (!SUPPORTED_TYPES[chart.config.type]) {
467        return;
468      }
469      chart._labels.forEach(function (label) {
470        label.args[args.index] = args;
471      });
472    },
473    beforeDraw: function (chart) {
474      if (!SUPPORTED_TYPES[chart.config.type]) {
475        return;
476      }
477      chart._labels.forEach(function (label) {
478        label.barTotalPercentage = {};
479      });
480    },
481    afterDatasetsDraw: function (chart) {
482      if (!SUPPORTED_TYPES[chart.config.type]) {
483        return;
484      }
485      chart._labels.forEach(function (label) {
486        label.render();
487      });
488    }
489  });
490})();

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.