%PDF-1.5 %���� ºaâÚÎΞ-ÌE1ÍØÄ÷{òò2ÿ ÛÖ^ÔÀá TÎ{¦?§®¥kuµùÕ5sLOšuY
Server IP : 49.231.201.246 / Your IP : 216.73.216.149 Web Server : Apache/2.4.18 (Ubuntu) System : Linux 246 4.4.0-210-generic #242-Ubuntu SMP Fri Apr 16 09:57:56 UTC 2021 x86_64 User : root ( 0) PHP Version : 7.0.33-0ubuntu0.16.04.16 Disable Function : exec,passthru,shell_exec,system,proc_open,popen,pcntl_exec MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : ON | Pkexec : ON Directory : /proc/11584/root/var/www/html/ppaobm/vendor/bower-asset/chartjs/src/core/ |
Upload File : |
'use strict'; var Animation = require('./core.animation'); var animations = require('./core.animations'); var controllers = require('../controllers/index'); var defaults = require('./core.defaults'); var helpers = require('../helpers/index'); var Interaction = require('./core.interaction'); var layouts = require('./core.layouts'); var platform = require('../platforms/platform'); var plugins = require('./core.plugins'); var scaleService = require('../core/core.scaleService'); var Tooltip = require('./core.tooltip'); var valueOrDefault = helpers.valueOrDefault; defaults._set('global', { elements: {}, events: [ 'mousemove', 'mouseout', 'click', 'touchstart', 'touchmove' ], hover: { onHover: null, mode: 'nearest', intersect: true, animationDuration: 400 }, onClick: null, maintainAspectRatio: true, responsive: true, responsiveAnimationDuration: 0 }); /** * Recursively merge the given config objects representing the `scales` option * by incorporating scale defaults in `xAxes` and `yAxes` array items, then * returns a deep copy of the result, thus doesn't alter inputs. */ function mergeScaleConfig(/* config objects ... */) { return helpers.merge({}, [].slice.call(arguments), { merger: function(key, target, source, options) { if (key === 'xAxes' || key === 'yAxes') { var slen = source[key].length; var i, type, scale; if (!target[key]) { target[key] = []; } for (i = 0; i < slen; ++i) { scale = source[key][i]; type = valueOrDefault(scale.type, key === 'xAxes' ? 'category' : 'linear'); if (i >= target[key].length) { target[key].push({}); } if (!target[key][i].type || (scale.type && scale.type !== target[key][i].type)) { // new/untyped scale or type changed: let's apply the new defaults // then merge source scale to correctly overwrite the defaults. helpers.merge(target[key][i], [scaleService.getScaleDefaults(type), scale]); } else { // scales type are the same helpers.merge(target[key][i], scale); } } } else { helpers._merger(key, target, source, options); } } }); } /** * Recursively merge the given config objects as the root options by handling * default scale options for the `scales` and `scale` properties, then returns * a deep copy of the result, thus doesn't alter inputs. */ function mergeConfig(/* config objects ... */) { return helpers.merge({}, [].slice.call(arguments), { merger: function(key, target, source, options) { var tval = target[key] || {}; var sval = source[key]; if (key === 'scales') { // scale config merging is complex. Add our own function here for that target[key] = mergeScaleConfig(tval, sval); } else if (key === 'scale') { // used in polar area & radar charts since there is only one scale target[key] = helpers.merge(tval, [scaleService.getScaleDefaults(sval.type), sval]); } else { helpers._merger(key, target, source, options); } } }); } function initConfig(config) { config = config || {}; // Do NOT use mergeConfig for the data object because this method merges arrays // and so would change references to labels and datasets, preventing data updates. var data = config.data = config.data || {}; data.datasets = data.datasets || []; data.labels = data.labels || []; config.options = mergeConfig( defaults.global, defaults[config.type], config.options || {}); return config; } function updateConfig(chart) { var newOptions = chart.options; helpers.each(chart.scales, function(scale) { layouts.removeBox(chart, scale); }); newOptions = mergeConfig( defaults.global, defaults[chart.config.type], newOptions); chart.options = chart.config.options = newOptions; chart.ensureScalesHaveIDs(); chart.buildOrUpdateScales(); // Tooltip chart.tooltip._options = newOptions.tooltips; chart.tooltip.initialize(); } function positionIsHorizontal(position) { return position === 'top' || position === 'bottom'; } var Chart = function(item, config) { this.construct(item, config); return this; }; helpers.extend(Chart.prototype, /** @lends Chart */ { /** * @private */ construct: function(item, config) { var me = this; config = initConfig(config); var context = platform.acquireContext(item, config); var canvas = context && context.canvas; var height = canvas && canvas.height; var width = canvas && canvas.width; me.id = helpers.uid(); me.ctx = context; me.canvas = canvas; me.config = config; me.width = width; me.height = height; me.aspectRatio = height ? width / height : null; me.options = config.options; me._bufferedRender = false; /** * Provided for backward compatibility, Chart and Chart.Controller have been merged, * the "instance" still need to be defined since it might be called from plugins. * @prop Chart#chart * @deprecated since version 2.6.0 * @todo remove at version 3 * @private */ me.chart = me; me.controller = me; // chart.chart.controller #inception // Add the chart instance to the global namespace Chart.instances[me.id] = me; // Define alias to the config data: `chart.data === chart.config.data` Object.defineProperty(me, 'data', { get: function() { return me.config.data; }, set: function(value) { me.config.data = value; } }); if (!context || !canvas) { // The given item is not a compatible context2d element, let's return before finalizing // the chart initialization but after setting basic chart / controller properties that // can help to figure out that the chart is not valid (e.g chart.canvas !== null); // https://github.com/chartjs/Chart.js/issues/2807 console.error("Failed to create chart: can't acquire context from the given item"); return; } me.initialize(); me.update(); }, /** * @private */ initialize: function() { var me = this; // Before init plugin notification plugins.notify(me, 'beforeInit'); helpers.retinaScale(me, me.options.devicePixelRatio); me.bindEvents(); if (me.options.responsive) { // Initial resize before chart draws (must be silent to preserve initial animations). me.resize(true); } // Make sure scales have IDs and are built before we build any controllers. me.ensureScalesHaveIDs(); me.buildOrUpdateScales(); me.initToolTip(); // After init plugin notification plugins.notify(me, 'afterInit'); return me; }, clear: function() { helpers.canvas.clear(this); return this; }, stop: function() { // Stops any current animation loop occurring animations.cancelAnimation(this); return this; }, resize: function(silent) { var me = this; var options = me.options; var canvas = me.canvas; var aspectRatio = (options.maintainAspectRatio && me.aspectRatio) || null; // the canvas render width and height will be casted to integers so make sure that // the canvas display style uses the same integer values to avoid blurring effect. // Set to 0 instead of canvas.size because the size defaults to 300x150 if the element is collapsed var newWidth = Math.max(0, Math.floor(helpers.getMaximumWidth(canvas))); var newHeight = Math.max(0, Math.floor(aspectRatio ? newWidth / aspectRatio : helpers.getMaximumHeight(canvas))); if (me.width === newWidth && me.height === newHeight) { return; } canvas.width = me.width = newWidth; canvas.height = me.height = newHeight; canvas.style.width = newWidth + 'px'; canvas.style.height = newHeight + 'px'; helpers.retinaScale(me, options.devicePixelRatio); if (!silent) { // Notify any plugins about the resize var newSize = {width: newWidth, height: newHeight}; plugins.notify(me, 'resize', [newSize]); // Notify of resize if (options.onResize) { options.onResize(me, newSize); } me.stop(); me.update({ duration: options.responsiveAnimationDuration }); } }, ensureScalesHaveIDs: function() { var options = this.options; var scalesOptions = options.scales || {}; var scaleOptions = options.scale; helpers.each(scalesOptions.xAxes, function(xAxisOptions, index) { xAxisOptions.id = xAxisOptions.id || ('x-axis-' + index); }); helpers.each(scalesOptions.yAxes, function(yAxisOptions, index) { yAxisOptions.id = yAxisOptions.id || ('y-axis-' + index); }); if (scaleOptions) { scaleOptions.id = scaleOptions.id || 'scale'; } }, /** * Builds a map of scale ID to scale object for future lookup. */ buildOrUpdateScales: function() { var me = this; var options = me.options; var scales = me.scales || {}; var items = []; var updated = Object.keys(scales).reduce(function(obj, id) { obj[id] = false; return obj; }, {}); if (options.scales) { items = items.concat( (options.scales.xAxes || []).map(function(xAxisOptions) { return {options: xAxisOptions, dtype: 'category', dposition: 'bottom'}; }), (options.scales.yAxes || []).map(function(yAxisOptions) { return {options: yAxisOptions, dtype: 'linear', dposition: 'left'}; }) ); } if (options.scale) { items.push({ options: options.scale, dtype: 'radialLinear', isDefault: true, dposition: 'chartArea' }); } helpers.each(items, function(item) { var scaleOptions = item.options; var id = scaleOptions.id; var scaleType = valueOrDefault(scaleOptions.type, item.dtype); if (positionIsHorizontal(scaleOptions.position) !== positionIsHorizontal(item.dposition)) { scaleOptions.position = item.dposition; } updated[id] = true; var scale = null; if (id in scales && scales[id].type === scaleType) { scale = scales[id]; scale.options = scaleOptions; scale.ctx = me.ctx; scale.chart = me; } else { var scaleClass = scaleService.getScaleConstructor(scaleType); if (!scaleClass) { return; } scale = new scaleClass({ id: id, type: scaleType, options: scaleOptions, ctx: me.ctx, chart: me }); scales[scale.id] = scale; } scale.mergeTicksOptions(); // TODO(SB): I think we should be able to remove this custom case (options.scale) // and consider it as a regular scale part of the "scales"" map only! This would // make the logic easier and remove some useless? custom code. if (item.isDefault) { me.scale = scale; } }); // clear up discarded scales helpers.each(updated, function(hasUpdated, id) { if (!hasUpdated) { delete scales[id]; } }); me.scales = scales; scaleService.addScalesToLayout(this); }, buildOrUpdateControllers: function() { var me = this; var newControllers = []; helpers.each(me.data.datasets, function(dataset, datasetIndex) { var meta = me.getDatasetMeta(datasetIndex); var type = dataset.type || me.config.type; if (meta.type && meta.type !== type) { me.destroyDatasetMeta(datasetIndex); meta = me.getDatasetMeta(datasetIndex); } meta.type = type; if (meta.controller) { meta.controller.updateIndex(datasetIndex); meta.controller.linkScales(); } else { var ControllerClass = controllers[meta.type]; if (ControllerClass === undefined) { throw new Error('"' + meta.type + '" is not a chart type.'); } meta.controller = new ControllerClass(me, datasetIndex); newControllers.push(meta.controller); } }, me); return newControllers; }, /** * Reset the elements of all datasets * @private */ resetElements: function() { var me = this; helpers.each(me.data.datasets, function(dataset, datasetIndex) { me.getDatasetMeta(datasetIndex).controller.reset(); }, me); }, /** * Resets the chart back to it's state before the initial animation */ reset: function() { this.resetElements(); this.tooltip.initialize(); }, update: function(config) { var me = this; if (!config || typeof config !== 'object') { // backwards compatibility config = { duration: config, lazy: arguments[1] }; } updateConfig(me); // plugins options references might have change, let's invalidate the cache // https://github.com/chartjs/Chart.js/issues/5111#issuecomment-355934167 plugins._invalidate(me); if (plugins.notify(me, 'beforeUpdate') === false) { return; } // In case the entire data object changed me.tooltip._data = me.data; // Make sure dataset controllers are updated and new controllers are reset var newControllers = me.buildOrUpdateControllers(); // Make sure all dataset controllers have correct meta data counts helpers.each(me.data.datasets, function(dataset, datasetIndex) { me.getDatasetMeta(datasetIndex).controller.buildOrUpdateElements(); }, me); me.updateLayout(); // Can only reset the new controllers after the scales have been updated if (me.options.animation && me.options.animation.duration) { helpers.each(newControllers, function(controller) { controller.reset(); }); } me.updateDatasets(); // Need to reset tooltip in case it is displayed with elements that are removed // after update. me.tooltip.initialize(); // Last active contains items that were previously in the tooltip. // When we reset the tooltip, we need to clear it me.lastActive = []; // Do this before render so that any plugins that need final scale updates can use it plugins.notify(me, 'afterUpdate'); if (me._bufferedRender) { me._bufferedRequest = { duration: config.duration, easing: config.easing, lazy: config.lazy }; } else { me.render(config); } }, /** * Updates the chart layout unless a plugin returns `false` to the `beforeLayout` * hook, in which case, plugins will not be called on `afterLayout`. * @private */ updateLayout: function() { var me = this; if (plugins.notify(me, 'beforeLayout') === false) { return; } layouts.update(this, this.width, this.height); /** * Provided for backward compatibility, use `afterLayout` instead. * @method IPlugin#afterScaleUpdate * @deprecated since version 2.5.0 * @todo remove at version 3 * @private */ plugins.notify(me, 'afterScaleUpdate'); plugins.notify(me, 'afterLayout'); }, /** * Updates all datasets unless a plugin returns `false` to the `beforeDatasetsUpdate` * hook, in which case, plugins will not be called on `afterDatasetsUpdate`. * @private */ updateDatasets: function() { var me = this; if (plugins.notify(me, 'beforeDatasetsUpdate') === false) { return; } for (var i = 0, ilen = me.data.datasets.length; i < ilen; ++i) { me.updateDataset(i); } plugins.notify(me, 'afterDatasetsUpdate'); }, /** * Updates dataset at index unless a plugin returns `false` to the `beforeDatasetUpdate` * hook, in which case, plugins will not be called on `afterDatasetUpdate`. * @private */ updateDataset: function(index) { var me = this; var meta = me.getDatasetMeta(index); var args = { meta: meta, index: index }; if (plugins.notify(me, 'beforeDatasetUpdate', [args]) === false) { return; } meta.controller.update(); plugins.notify(me, 'afterDatasetUpdate', [args]); }, render: function(config) { var me = this; if (!config || typeof config !== 'object') { // backwards compatibility config = { duration: config, lazy: arguments[1] }; } var animationOptions = me.options.animation; var duration = valueOrDefault(config.duration, animationOptions && animationOptions.duration); var lazy = config.lazy; if (plugins.notify(me, 'beforeRender') === false) { return; } var onComplete = function(animation) { plugins.notify(me, 'afterRender'); helpers.callback(animationOptions && animationOptions.onComplete, [animation], me); }; if (animationOptions && duration) { var animation = new Animation({ numSteps: duration / 16.66, // 60 fps easing: config.easing || animationOptions.easing, render: function(chart, animationObject) { var easingFunction = helpers.easing.effects[animationObject.easing]; var currentStep = animationObject.currentStep; var stepDecimal = currentStep / animationObject.numSteps; chart.draw(easingFunction(stepDecimal), stepDecimal, currentStep); }, onAnimationProgress: animationOptions.onProgress, onAnimationComplete: onComplete }); animations.addAnimation(me, animation, duration, lazy); } else { me.draw(); // See https://github.com/chartjs/Chart.js/issues/3781 onComplete(new Animation({numSteps: 0, chart: me})); } return me; }, draw: function(easingValue) { var me = this; me.clear(); if (helpers.isNullOrUndef(easingValue)) { easingValue = 1; } me.transition(easingValue); if (me.width <= 0 || me.height <= 0) { return; } if (plugins.notify(me, 'beforeDraw', [easingValue]) === false) { return; } // Draw all the scales helpers.each(me.boxes, function(box) { box.draw(me.chartArea); }, me); me.drawDatasets(easingValue); me._drawTooltip(easingValue); plugins.notify(me, 'afterDraw', [easingValue]); }, /** * @private */ transition: function(easingValue) { var me = this; for (var i = 0, ilen = (me.data.datasets || []).length; i < ilen; ++i) { if (me.isDatasetVisible(i)) { me.getDatasetMeta(i).controller.transition(easingValue); } } me.tooltip.transition(easingValue); }, /** * Draws all datasets unless a plugin returns `false` to the `beforeDatasetsDraw` * hook, in which case, plugins will not be called on `afterDatasetsDraw`. * @private */ drawDatasets: function(easingValue) { var me = this; if (plugins.notify(me, 'beforeDatasetsDraw', [easingValue]) === false) { return; } // Draw datasets reversed to support proper line stacking for (var i = (me.data.datasets || []).length - 1; i >= 0; --i) { if (me.isDatasetVisible(i)) { me.drawDataset(i, easingValue); } } plugins.notify(me, 'afterDatasetsDraw', [easingValue]); }, /** * Draws dataset at index unless a plugin returns `false` to the `beforeDatasetDraw` * hook, in which case, plugins will not be called on `afterDatasetDraw`. * @private */ drawDataset: function(index, easingValue) { var me = this; var meta = me.getDatasetMeta(index); var args = { meta: meta, index: index, easingValue: easingValue }; if (plugins.notify(me, 'beforeDatasetDraw', [args]) === false) { return; } meta.controller.draw(easingValue); plugins.notify(me, 'afterDatasetDraw', [args]); }, /** * Draws tooltip unless a plugin returns `false` to the `beforeTooltipDraw` * hook, in which case, plugins will not be called on `afterTooltipDraw`. * @private */ _drawTooltip: function(easingValue) { var me = this; var tooltip = me.tooltip; var args = { tooltip: tooltip, easingValue: easingValue }; if (plugins.notify(me, 'beforeTooltipDraw', [args]) === false) { return; } tooltip.draw(); plugins.notify(me, 'afterTooltipDraw', [args]); }, /** * Get the single element that was clicked on * @return An object containing the dataset index and element index of the matching element. Also contains the rectangle that was draw */ getElementAtEvent: function(e) { return Interaction.modes.single(this, e); }, getElementsAtEvent: function(e) { return Interaction.modes.label(this, e, {intersect: true}); }, getElementsAtXAxis: function(e) { return Interaction.modes['x-axis'](this, e, {intersect: true}); }, getElementsAtEventForMode: function(e, mode, options) { var method = Interaction.modes[mode]; if (typeof method === 'function') { return method(this, e, options); } return []; }, getDatasetAtEvent: function(e) { return Interaction.modes.dataset(this, e, {intersect: true}); }, getDatasetMeta: function(datasetIndex) { var me = this; var dataset = me.data.datasets[datasetIndex]; if (!dataset._meta) { dataset._meta = {}; } var meta = dataset._meta[me.id]; if (!meta) { meta = dataset._meta[me.id] = { type: null, data: [], dataset: null, controller: null, hidden: null, // See isDatasetVisible() comment xAxisID: null, yAxisID: null }; } return meta; }, getVisibleDatasetCount: function() { var count = 0; for (var i = 0, ilen = this.data.datasets.length; i < ilen; ++i) { if (this.isDatasetVisible(i)) { count++; } } return count; }, isDatasetVisible: function(datasetIndex) { var meta = this.getDatasetMeta(datasetIndex); // meta.hidden is a per chart dataset hidden flag override with 3 states: if true or false, // the dataset.hidden value is ignored, else if null, the dataset hidden state is returned. return typeof meta.hidden === 'boolean' ? !meta.hidden : !this.data.datasets[datasetIndex].hidden; }, generateLegend: function() { return this.options.legendCallback(this); }, /** * @private */ destroyDatasetMeta: function(datasetIndex) { var id = this.id; var dataset = this.data.datasets[datasetIndex]; var meta = dataset._meta && dataset._meta[id]; if (meta) { meta.controller.destroy(); delete dataset._meta[id]; } }, destroy: function() { var me = this; var canvas = me.canvas; var i, ilen; me.stop(); // dataset controllers need to cleanup associated data for (i = 0, ilen = me.data.datasets.length; i < ilen; ++i) { me.destroyDatasetMeta(i); } if (canvas) { me.unbindEvents(); helpers.canvas.clear(me); platform.releaseContext(me.ctx); me.canvas = null; me.ctx = null; } plugins.notify(me, 'destroy'); delete Chart.instances[me.id]; }, toBase64Image: function() { return this.canvas.toDataURL.apply(this.canvas, arguments); }, initToolTip: function() { var me = this; me.tooltip = new Tooltip({ _chart: me, _chartInstance: me, // deprecated, backward compatibility _data: me.data, _options: me.options.tooltips }, me); }, /** * @private */ bindEvents: function() { var me = this; var listeners = me._listeners = {}; var listener = function() { me.eventHandler.apply(me, arguments); }; helpers.each(me.options.events, function(type) { platform.addEventListener(me, type, listener); listeners[type] = listener; }); // Elements used to detect size change should not be injected for non responsive charts. // See https://github.com/chartjs/Chart.js/issues/2210 if (me.options.responsive) { listener = function() { me.resize(); }; platform.addEventListener(me, 'resize', listener); listeners.resize = listener; } }, /** * @private */ unbindEvents: function() { var me = this; var listeners = me._listeners; if (!listeners) { return; } delete me._listeners; helpers.each(listeners, function(listener, type) { platform.removeEventListener(me, type, listener); }); }, updateHoverStyle: function(elements, mode, enabled) { var method = enabled ? 'setHoverStyle' : 'removeHoverStyle'; var element, i, ilen; for (i = 0, ilen = elements.length; i < ilen; ++i) { element = elements[i]; if (element) { this.getDatasetMeta(element._datasetIndex).controller[method](element); } } }, /** * @private */ eventHandler: function(e) { var me = this; var tooltip = me.tooltip; if (plugins.notify(me, 'beforeEvent', [e]) === false) { return; } // Buffer any update calls so that renders do not occur me._bufferedRender = true; me._bufferedRequest = null; var changed = me.handleEvent(e); // for smooth tooltip animations issue #4989 // the tooltip should be the source of change // Animation check workaround: // tooltip._start will be null when tooltip isn't animating if (tooltip) { changed = tooltip._start ? tooltip.handleEvent(e) : changed | tooltip.handleEvent(e); } plugins.notify(me, 'afterEvent', [e]); var bufferedRequest = me._bufferedRequest; if (bufferedRequest) { // If we have an update that was triggered, we need to do a normal render me.render(bufferedRequest); } else if (changed && !me.animating) { // If entering, leaving, or changing elements, animate the change via pivot me.stop(); // We only need to render at this point. Updating will cause scales to be // recomputed generating flicker & using more memory than necessary. me.render({ duration: me.options.hover.animationDuration, lazy: true }); } me._bufferedRender = false; me._bufferedRequest = null; return me; }, /** * Handle an event * @private * @param {IEvent} event the event to handle * @return {boolean} true if the chart needs to re-render */ handleEvent: function(e) { var me = this; var options = me.options || {}; var hoverOptions = options.hover; var changed = false; me.lastActive = me.lastActive || []; // Find Active Elements for hover and tooltips if (e.type === 'mouseout') { me.active = []; } else { me.active = me.getElementsAtEventForMode(e, hoverOptions.mode, hoverOptions); } // Invoke onHover hook // Need to call with native event here to not break backwards compatibility helpers.callback(options.onHover || options.hover.onHover, [e.native, me.active], me); if (e.type === 'mouseup' || e.type === 'click') { if (options.onClick) { // Use e.native here for backwards compatibility options.onClick.call(me, e.native, me.active); } } // Remove styling for last active (even if it may still be active) if (me.lastActive.length) { me.updateHoverStyle(me.lastActive, hoverOptions.mode, false); } // Built in hover styling if (me.active.length && hoverOptions.mode) { me.updateHoverStyle(me.active, hoverOptions.mode, true); } changed = !helpers.arrayEquals(me.active, me.lastActive); // Remember Last Actives me.lastActive = me.active; return changed; } }); /** * NOTE(SB) We actually don't use this container anymore but we need to keep it * for backward compatibility. Though, it can still be useful for plugins that * would need to work on multiple charts?! */ Chart.instances = {}; module.exports = Chart; // DEPRECATIONS /** * Provided for backward compatibility, use Chart instead. * @class Chart.Controller * @deprecated since version 2.6 * @todo remove at version 3 * @private */ Chart.Controller = Chart; /** * Provided for backward compatibility, not available anymore. * @namespace Chart * @deprecated since version 2.8 * @todo remove at version 3 * @private */ Chart.types = {}; /** * Provided for backward compatibility, not available anymore. * @namespace Chart.helpers.configMerge * @deprecated since version 2.8.0 * @todo remove at version 3 * @private */ helpers.configMerge = mergeConfig; /** * Provided for backward compatibility, not available anymore. * @namespace Chart.helpers.scaleMerge * @deprecated since version 2.8.0 * @todo remove at version 3 * @private */ helpers.scaleMerge = mergeScaleConfig;