@progress/kendo-charts
Version:
Kendo UI platform-independent Charts library
1,492 lines (1,209 loc) • 79.5 kB
JavaScript
import { drawing as draw, throttle, geometry } from '@progress/kendo-drawing';
import { RootElement, Title, CategoryAxis, Point } from '../core';
import Highlight from './highlight';
import Pannable from './pan-and-zoom/pannable';
import ZoomSelection from './pan-and-zoom/zoom-selection';
import MousewheelZoom from './pan-and-zoom/mousewheel-zoom';
import Legend from './legend/legend';
import PlotAreaFactory from './plotarea/plotarea-factory';
import Selection from './selection';
import SeriesBinder from './series-binder';
import Tooltip from './tooltip/tooltip';
import SharedTooltip from './tooltip/shared-tooltip';
import CategoricalPlotArea from './plotarea/categorical-plotarea';
import PlotAreaBase from './plotarea/plotarea-base';
import { ChartService, DomEventsBuilder } from '../services';
import isDateAxis from './utils/is-date-axis';
import { ChartPane, ChartPlotArea, findAxisByName } from './api-elements';
import { X, Y, VALUE, DEFAULT_WIDTH, DEFAULT_HEIGHT, DEFAULT_SERIES_OPACITY,
ARROW_DOWN, ARROW_UP, ARROW_LEFT, ARROW_RIGHT, ARIA_ACTIVE_DESCENDANT, TAB, TOP, LEFT, BLACK,
ENTER, ESCAPE, BOTTOM } from '../common/constants';
import { addClass, removeClass, Class, setDefaultOptions, deepExtend, defined, find, isObject, isFunction, elementSize, elementOffset,
elementScale, elementStyles, eventCoordinates, bindEvents, unbindEvents, mousewheelDelta, FontLoader, inArray, round,
valueOrDefault, isString, cycleUp, cycleDown, hasOwnProperty, hasClasses } from '../common';
import { DRAG_START, DRAG, DRAG_END, ZOOM_START, ZOOM, ZOOM_END, SELECT_START, SELECT, SELECT_END, PLOT_AREA_HOVER, PLOT_AREA_LEAVE,
RENDER, CATEGORY, PIE, DONUT, FUNNEL, PYRAMID, COLUMN, MOUSEWHEEL, MOUSEWHEEL_DELAY, MOUSEWHEEL_ZOOM_RATE, SHOW_TOOLTIP, SERIES_HOVER,
SERIES_OVER, SERIES_LEAVE, SERIES_CLICK, DRILLDOWN, LEGEND_ITEM_CLICK } from './constants';
import './animations';
import './register-charts';
import { parseDateCategory } from './utils';
var AXIS_NAMES = [ CATEGORY, VALUE, X, Y ];
var MOUSEDOWN = "mousedown";
var MOUSEMOVE = "mousemove";
var CONTEXTMENU = "contextmenu";
var MOUSELEAVE = "mouseleave";
var KEYDOWN = "keydown";
var FOCUS = "focus";
var BLUR = "blur";
var MOUSEMOVE_DELAY = 20;
var NO_DATA_OVERLAY_TOP_CLASS = "k-chart-overlay-top";
var Chart = (function (Class) {
function Chart(element, userOptions, themeOptions, context) {
var this$1 = this;
if ( context === void 0 ) context = {};
Class.call(this);
this.observers = [];
this.addObserver(context.observer);
this.chartService = new ChartService(this, context);
this.chartService.theme = themeOptions;
this._initElement(element);
var options = deepExtend({}, this.options, userOptions);
this._originalOptions = deepExtend({}, options);
this._theme = themeOptions;
this._initTheme(options, themeOptions);
this._focusState = {};
this._initHandlers();
this._initSurface();
this.bindCategories();
FontLoader.preloadFonts(userOptions, function () {
this$1.fontLoaded = true;
if (!this$1._destroyed) {
this$1.trigger('init');
this$1._redraw();
this$1._attachEvents();
this$1._restoreOverlayElement();
}
});
}
if ( Class ) Chart.__proto__ = Class;
Chart.prototype = Object.create( Class && Class.prototype );
Chart.prototype.constructor = Chart;
Chart.prototype._initElement = function _initElement (element) {
var this$1 = this;
this._setElementClass(element);
element.style.position = "relative";
element.tabIndex = element.getAttribute("tabindex") ? element.getAttribute("tabindex") : 0;
// To support user agents and assistive technologies based on the ARIA 1.0 specification, authors may wish to include the document role as a fallback value, in the form role="graphics-document document".
element.setAttribute("role", "graphics-document document");
for (var i = element.childNodes.length - 1; i >= 0; i--) {
var child = element.childNodes[i];
if (!hasClasses(child, "k-chart-overlay")) {
element.removeChild(child);
} else {
// this is necessary if the overlay is rendered server-side, e.g. in blazor
// but drawing the surface clears the contents of the element
// and thus the no data overlay is lost
this$1.overlayElement = child;
}
}
this.element = element;
};
Chart.prototype._setElementClass = function _setElementClass (element) {
addClass(element, "k-chart");
};
Chart.prototype._restoreOverlayElement = function _restoreOverlayElement () {
if (!this.overlayElement) {
return;
}
if (this._hasSeriesData()) {
this.overlayElement.style.display = "none";
} else {
if (!this.options.title || (this.options.title && this.options.title.position !== BOTTOM)) {
addClass(this.overlayElement, NO_DATA_OVERLAY_TOP_CLASS);
} else {
removeClass(this.overlayElement, NO_DATA_OVERLAY_TOP_CLASS);
}
this.overlayElement.style.display = "";
}
if (this.overlayElement.parentElement !== this.element) {
this.element.appendChild(this.overlayElement);
}
};
Chart.prototype._hasSeriesData = function _hasSeriesData () {
var series = this.options.series || [];
var hasData = series.length > 0 && series.some(function (x) { return x.data && x.data.length > 0; });
return hasData;
};
Chart.prototype._initTheme = function _initTheme (options, themeOptions) {
var seriesCopies = [];
var series = options.series || [];
for (var i = 0; i < series.length; i++) {
seriesCopies.push(Object.assign({}, series[i]));
}
options.series = seriesCopies;
resolveAxisAliases(options);
this.applyDefaults(options, themeOptions);
// Clean up default if not overriden by data attributes
if (options.seriesColors === null) {
delete options.seriesColors;
}
if (isString(options.title)) {
options.title = { text: options.title };
}
this.options = deepExtend({}, themeOptions, options);
this.applySeriesColors();
};
Chart.prototype.getSize = function getSize () {
var chartArea = this.options.chartArea || {};
var width = chartArea.width ? parseInt(chartArea.width, 10) : Math.floor(this.element.offsetWidth);
var height = chartArea.height ? parseInt(chartArea.height, 10) : Math.floor(this.element.offsetHeight);
return {
width: width,
height: height
};
};
Chart.prototype.resize = function resize (force) {
var size = this.getSize();
var currentSize = this._size;
var hasSize = size.width > 0 || size.height > 0;
if (force || hasSize && (!currentSize || size.width !== currentSize.width || size.height !== currentSize.height)) {
this._size = size;
this._resize(size, force);
this.trigger("resize", size);
} else if (hasSize && this._selections && find(this._selections, function (s) { return !s.visible; })) {
this._destroySelections();
this._setupSelection();
}
};
Chart.prototype._resize = function _resize () {
this._noTransitionsRedraw();
};
Chart.prototype.redraw = function redraw (paneName) {
this.applyDefaults(this.options);
this.applySeriesColors();
if (paneName) {
var plotArea = this._model._plotArea;
var pane = plotArea.findPane(paneName);
plotArea.redraw(pane);
} else {
this._redraw();
}
};
Chart.prototype.getAxis = function getAxis (name) {
return findAxisByName(name, this._plotArea.axes);
};
Chart.prototype.findAxisByName = function findAxisByName (name) {
return this.getAxis(name);
};
Chart.prototype.findPaneByName = function findPaneByName (name) {
var panes = this._plotArea.panes;
for (var idx = 0; idx < panes.length; idx++) {
if (panes[idx].options.name === name) {
return new ChartPane(panes[idx]);
}
}
};
Chart.prototype.findPaneByIndex = function findPaneByIndex (idx) {
var panes = this._plotArea.panes;
if (panes[idx]) {
return new ChartPane(panes[idx]);
}
};
Chart.prototype.plotArea = function plotArea () {
return new ChartPlotArea(this._plotArea);
};
Chart.prototype.toggleHighlight = function toggleHighlight (show, filter) {
var plotArea = this._plotArea;
var firstSeries = (plotArea.srcSeries || plotArea.series || [])[0];
var points;
if (isFunction(filter)) {
points = plotArea.filterPoints(filter);
} else {
var seriesName, categoryName;
if (isObject(filter)) {
seriesName = filter.series;
categoryName = filter.category;
} else {
seriesName = categoryName = filter;
}
if (firstSeries.type === DONUT) {
points = pointByCategoryName(plotArea.pointsBySeriesName(seriesName), categoryName);
} else if (inArray(firstSeries.type, [ PIE, FUNNEL, PYRAMID ])) {
points = pointByCategoryName((plotArea.charts[0] || {}).points, categoryName);
} else {
points = plotArea.pointsBySeriesName(seriesName);
}
}
if (points) {
this.togglePointsHighlight(show, points);
}
};
Chart.prototype.togglePointsHighlight = function togglePointsHighlight (show, points) {
var highlight = this._highlight;
for (var idx = 0; idx < points.length; idx++) {
highlight.togglePointHighlight(points[idx], show);
}
};
Chart.prototype.showTooltip = function showTooltip (filter) {
var shared = this._sharedTooltip();
var ref = this;
var tooltip = ref._tooltip;
var plotArea = ref._plotArea;
var point, categoryIndex;
if (isFunction(filter)) {
point = plotArea.findPoint(filter);
if (point && shared) {
categoryIndex = point.categoryIx;
}
} else if (shared && defined(filter)) {
categoryIndex = plotArea.categoryAxis.categoryIndex(filter);
}
if (shared) {
if (categoryIndex >= 0) {
var points = this._plotArea.pointsByCategoryIndex(categoryIndex);
tooltip.showAt(points);
}
} else if (point) {
tooltip.show(point);
}
};
Chart.prototype.hideTooltip = function hideTooltip () {
this._tooltip.hide();
};
Chart.prototype._initSurface = function _initSurface () {
var surface = this.surface;
var wrap = this._surfaceWrap();
var chartArea = this.options.chartArea || {};
if (chartArea.width) {
elementSize(wrap, { width: chartArea.width });
}
if (chartArea.height) {
elementSize(wrap, { height: chartArea.height });
}
if (!surface || surface.options.type !== this.options.renderAs) {
this._destroySurface();
this.surface = draw.Surface.create(wrap, {
type: this.options.renderAs
});
this.surface.bind("mouseenter", this._surfaceMouseenterHandler);
this.surface.bind("mouseleave", this._surfaceMouseleaveHandler);
} else {
this.surface.clear();
this.surface.resize();
}
// Override the surface _kendoExportVisual in order to accept export options with size.
this.element._kendoExportVisual = this._kendoExportVisual.bind(this);
};
Chart.prototype._surfaceWrap = function _surfaceWrap () {
return this.element;
};
Chart.prototype._redraw = function _redraw () {
var model = this._getModel();
this._size = {
width: model.options.width,
height: model.options.height
};
this._destroyView();
this._setElementAccessibilityAttributes();
this._model = model;
this._plotArea = model._plotArea;
this._legend = model._legend;
model.renderVisual();
if (this.options.transitions !== false) {
model.traverse(function(element) {
if (element.animation) {
element.animation.setup();
}
});
}
this._initSurface();
this.surface.draw(model.visual);
if (this.options.transitions !== false) {
model.traverse(function(element) {
if (element.animation) {
element.animation.play();
}
});
}
this._tooltip = this._createTooltip();
this._highlight = new Highlight();
this._setupSelection();
this._createPannable();
this._createZoomSelection();
this._createMousewheelZoom();
this._setComputedStyles();
this.trigger(RENDER);
triggerPaneRender(this._plotArea.panes);
if (!this._navState) {
this._cancelDomEvents();
}
this._redrawFocusHighlight();
};
Chart.prototype._setComputedStyles = function _setComputedStyles () {
var titleHeight = this.titleHeight();
this.element.style.setProperty('--kendo-chart-computed-title-height', (titleHeight + "px"));
};
Chart.prototype._redrawFocusHighlight = function _redrawFocusHighlight () {
if (this._destroyed) {
return;
}
var ref = this;
var ref_focusState = ref._focusState;
var legendInFocus = ref_focusState.legendInFocus;
var preserveHighlight = ref_focusState.preserveHighlight;
if (legendInFocus && preserveHighlight) {
this._focusElement(this._getFocusedLegendItem(), false);
this._focusState.preserveHighlight = false;
}
};
Chart.prototype._setElementAccessibilityAttributes = function _setElementAccessibilityAttributes () {
var titleOptions = this.options.title;
var title = isString(titleOptions) ? titleOptions : (titleOptions.description || titleOptions.text);
if (title) {
this.element.setAttribute("aria-roledescription", title);
}
};
Chart.prototype._kendoExportVisual = function _kendoExportVisual (size) {
if (size && size.width && size.height) {
var chartArea = this._originalOptions.chartArea || {};
var exportOptions = {
width: chartArea.width || size.width,
height: chartArea.height || size.height
};
return this.exportVisual(exportOptions);
}
return this.exportVisual();
};
Chart.prototype.exportVisual = function exportVisual (exportOptions) {
var visual;
if (exportOptions && (exportOptions.width || exportOptions.height || exportOptions.options)) {
var currentOptions = this.options;
var options = deepExtend({}, exportOptions.options, {
chartArea: {
width: exportOptions.width,
height: exportOptions.height
}
});
clearMissingValues(this._originalOptions, options);
this.options = deepExtend({}, this._originalOptions, options);
this._initTheme(this.options, this._theme);
this.bindCategories();
var model = this._getModel();
model.renderVisual();
triggerPaneRender(model._plotArea.panes);
visual = model.visual;
this.options = currentOptions;
} else {
visual = this.surface.exportVisual();
}
return visual;
};
Chart.prototype._sharedTooltip = function _sharedTooltip () {
return this._plotArea instanceof CategoricalPlotArea && this.options.tooltip && this.options.tooltip.shared;
};
Chart.prototype._createPannable = function _createPannable () {
var options = this.options;
if (options.pannable !== false) {
this._pannable = new Pannable(this._plotArea, options.pannable);
}
};
Chart.prototype._createZoomSelection = function _createZoomSelection () {
var zoomable = this.options.zoomable;
var selection = (zoomable || {}).selection;
if (zoomable !== false && selection !== false) {
this._zoomSelection = new ZoomSelection(this, selection);
}
};
Chart.prototype._createMousewheelZoom = function _createMousewheelZoom () {
var zoomable = this.options.zoomable;
var mousewheel = (zoomable || {}).mousewheel;
if (zoomable !== false && mousewheel !== false) {
this._mousewheelZoom = new MousewheelZoom(this, mousewheel);
}
};
Chart.prototype._toggleDragZoomEvents = function _toggleDragZoomEvents () {
var pannable = this.options.pannable;
var zoomable = this.options.zoomable;
var selection = (zoomable || {}).selection;
var mousewheel = (zoomable || {}).mousewheel;
var allowDrag = !pannable && (zoomable === false || selection === false) && !this.requiresHandlers([ DRAG_START, DRAG, DRAG_END ]);
var allowZoom = (zoomable === false || mousewheel === false) && !this.requiresHandlers([ ZOOM_START, ZOOM, ZOOM_END ]);
var element = this.element;
if (this._dragZoomEnabled && allowDrag && allowZoom) {
element.style.touchAction = this._touchAction || '';
this._dragZoomEnabled = false;
} else if (!this._dragZoomEnabled && !(allowDrag && allowZoom)) {
element.style.touchAction = "none";
this._dragZoomEnabled = true;
}
this._toggleDomEvents(!allowDrag, !allowZoom);
};
Chart.prototype._toggleDomEvents = function _toggleDomEvents (drag, zoom) {
var domEvents = this.domEvents;
if (!domEvents) {
return;
}
if (domEvents.toggleDrag) {
domEvents.toggleDrag(drag);
}
if (domEvents.toggleZoom) {
domEvents.toggleZoom(zoom);
}
};
Chart.prototype._createTooltip = function _createTooltip () {
var ref = this;
var tooltipOptions = ref.options.tooltip;
var tooltip;
if (this._sharedTooltip()) {
tooltip = this._createSharedTooltip(tooltipOptions);
} else {
tooltip = new Tooltip(this.chartService, tooltipOptions);
}
return tooltip;
};
Chart.prototype._createSharedTooltip = function _createSharedTooltip (options) {
return new SharedTooltip(this._plotArea, options);
};
Chart.prototype.applyDefaults = function applyDefaults (options, themeOptions) {
applyAxisDefaults(options, themeOptions);
applySeriesDefaults(options, themeOptions);
};
Chart.prototype.applySeriesColors = function applySeriesColors () {
var options = this.options;
var series = options.series;
var colors = options.seriesColors || [];
for (var i = 0; i < series.length; i++) {
var currentSeries = series[i];
var seriesColor = colors[i % colors.length];
var defaults = currentSeries._defaults;
currentSeries.color = currentSeries.color || seriesColor;
if (defaults) {
defaults.color = defaults.color || seriesColor;
}
}
};
Chart.prototype._getModel = function _getModel () {
var options = this.options;
var plotArea = this._createPlotArea();
var model = new RootElement(this._modelOptions());
model.chart = this;
model._plotArea = plotArea;
var title = Title.buildTitle(options.title);
var subtitle = Title.buildTitle(options.subtitle, {
align: options.title.align,
position: options.title.position
});
model.append.apply(model, Title.orderTitles([title, subtitle]));
if (options.legend && options.legend.visible) {
var legend = new Legend(plotArea.options.legend, this.chartService);
model.append(legend);
model._legend = legend;
}
model.append(plotArea);
model.reflow();
this._setTitleBox(title, subtitle);
return model;
};
Chart.prototype._setTitleBox = function _setTitleBox (title, subtitle) {
if (!title && !subtitle) {
return;
}
this._titleBox = (title || subtitle).box.clone();
var titlePosition = title ? title.options.position : '';
var subtitlePosition = subtitle ? subtitle.options.position : '';
var samePosition = titlePosition === subtitlePosition;
var subtitleAtTop = subtitlePosition !== BOTTOM;
if (samePosition && subtitle) {
this._titleBox.wrap(subtitle.box);
} else if (title && subtitle && subtitleAtTop) {
this._titleBox = subtitle.box.clone();
}
};
Chart.prototype._modelOptions = function _modelOptions () {
var options = this.options;
var size = this.getSize();
return deepExtend({
transitions: options.transitions,
width: size.width || DEFAULT_WIDTH,
height: size.height || DEFAULT_HEIGHT
}, options.chartArea);
};
Chart.prototype._createPlotArea = function _createPlotArea (skipSeries) {
var options = this.options;
var plotArea = PlotAreaFactory.current.create(skipSeries ? [] : options.series, options, this.chartService);
return plotArea;
};
Chart.prototype._setupSelection = function _setupSelection () {
var this$1 = this;
var ref = this;
var axes = ref._plotArea.axes;
var selections = this._selections = [];
for (var i = 0; i < axes.length; i++) {
var axis = axes[i];
var options = axis.options;
if (axis instanceof CategoryAxis && options.select && !options.vertical) {
var range = axis.range();
var selection = new Selection(this$1, axis,
deepExtend({ min: range.min, max: range.max }, options.select)
);
selections.push(selection);
}
}
};
Chart.prototype._selectStart = function _selectStart (e) {
return this.trigger(SELECT_START, e);
};
Chart.prototype._select = function _select (e) {
return this.trigger(SELECT, e);
};
Chart.prototype._selectEnd = function _selectEnd (e) {
return this.trigger(SELECT_END, e);
};
Chart.prototype._initHandlers = function _initHandlers () {
this._clickHandler = this._click.bind(this);
this._keydownHandler = this._keydown.bind(this);
this._focusHandler = this._focus.bind(this);
this._blurHandler = this._blur.bind(this);
this._mousedownHandler = this._mousedown.bind(this);
this._mousewheelHandler = this._mousewheel.bind(this);
this._mouseleaveHandler = this._mouseleave.bind(this);
this._surfaceMouseenterHandler = this._mouseover.bind(this);
this._surfaceMouseleaveHandler = this._mouseout.bind(this);
this._mousemove = throttle(
this._mousemove.bind(this),
MOUSEMOVE_DELAY
);
};
Chart.prototype.addObserver = function addObserver (observer) {
if (observer) {
this.observers.push(observer);
}
};
Chart.prototype.removeObserver = function removeObserver (observer) {
var index = this.observers.indexOf(observer);
if (index >= 0) {
this.observers.splice(index, 1);
}
};
Chart.prototype.requiresHandlers = function requiresHandlers (eventNames) {
var observers = this.observers;
for (var idx = 0; idx < observers.length; idx++) {
if (observers[idx].requiresHandlers(eventNames)) {
return true;
}
}
};
Chart.prototype.trigger = function trigger (name, args) {
if ( args === void 0 ) args = {};
args.sender = this;
if (name === SHOW_TOOLTIP) {
args.anchor.point = this._toDocumentCoordinates(args.anchor.point);
} else if (name === SERIES_OVER) {
this._updateDrilldownPoint(args.point);
} else if (name === SERIES_LEAVE) {
this._resetDrilldownPoint();
} else if (name === SERIES_CLICK) {
this._focusPoint(args.point);
this._startDrilldown(args.point);
} else if (name === LEGEND_ITEM_CLICK) {
this._focusLegendItem(args);
}
var observers = this.observers;
var isDefaultPrevented = false;
for (var idx = 0; idx < observers.length; idx++) {
if (observers[idx].trigger(name, args)) {
isDefaultPrevented = true;
}
}
return isDefaultPrevented;
};
Chart.prototype.titleHeight = function titleHeight () {
if (!this._titleBox) {
return 0;
}
return this._titleBox.height();
};
Chart.prototype._attachEvents = function _attachEvents () {
var obj, obj$1;
var element = this.element;
this._touchAction = element.style.touchAction;
bindEvents(element, ( obj = {}, obj[ CONTEXTMENU ] = this._clickHandler, obj[ MOUSEWHEEL ] = this._mousewheelHandler, obj[ MOUSELEAVE ] = this._mouseleaveHandler, obj[ KEYDOWN ] = this._keydownHandler, obj[ MOUSEDOWN ] = this._mousedownHandler, obj[ FOCUS ] = this._focusHandler, obj[ BLUR] = this._blurHandler, obj ));
if (this._shouldAttachMouseMove()) {
bindEvents(element, ( obj$1 = {}, obj$1[ MOUSEMOVE ] = this._mousemove, obj$1 ));
}
this.domEvents = DomEventsBuilder.create(this.element, {
start: this._start.bind(this),
move: this._move.bind(this),
end: this._end.bind(this),
tap: this._tap.bind(this),
gesturestart: this._gesturestart.bind(this),
gesturechange: this._gesturechange.bind(this),
gestureend: this._gestureend.bind(this)
});
this._toggleDragZoomEvents();
};
Chart.prototype._mouseleave = function _mouseleave (e) {
if (this._hoveredPoint) {
this._hoveredPoint.out(this, e);
this._hoveredPoint = null;
}
if (this._plotAreaHovered) {
this._plotAreaHovered = false;
this.trigger(PLOT_AREA_LEAVE);
}
if (this._hasInactiveOpacity() && this._activeChartInstance) {
this._applySeriesOpacity(this._activeChartInstance.children, null, true);
this._updateSeriesOpacity(null, true);
}
};
Chart.prototype._cancelDomEvents = function _cancelDomEvents () {
if (this.domEvents && this.domEvents.cancel) {
this.domEvents.cancel();
}
};
Chart.prototype._gesturestart = function _gesturestart (e) {
if (this._mousewheelZoom && !this._stopChartHandlers(e)) {
this._gestureDistance = e.distance;
this._unsetActivePoint();
this._clearFocusedElement();
this.surface.suspendTracking();
}
};
Chart.prototype._gestureend = function _gestureend (e) {
if (this._zooming && !this._stopChartHandlers(e)) {
if (this.surface) {
this.surface.resumeTracking();
}
this._zooming = false;
this.trigger(ZOOM_END, {});
}
};
Chart.prototype._gesturechange = function _gesturechange (e) {
var mousewheelZoom = this._mousewheelZoom;
if (mousewheelZoom && !this._stopChartHandlers(e)) {
e.preventDefault();
var previousGestureDistance = this._gestureDistance;
var scaleDelta = -e.distance / previousGestureDistance + 1;
if (Math.abs(scaleDelta) >= 0.1) {
scaleDelta = Math.round(scaleDelta * 10);
this._gestureDistance = e.distance;
var args = { delta: scaleDelta, axisRanges: axisRanges(this._plotArea.axes), originalEvent: e };
if (this._zooming || !this.trigger(ZOOM_START, args)) {
var coords = this._eventCoordinates(e);
if (!this._zooming) {
this._zooming = true;
}
var ranges = args.axisRanges = mousewheelZoom.updateRanges(scaleDelta, coords);
if (ranges && !this.trigger(ZOOM, args)) {
mousewheelZoom.zoom();
}
}
}
}
};
Chart.prototype._mouseout = function _mouseout (e) {
if (e.element) {
var element = this._drawingChartElement(e.element, e);
if (element && element.leave) {
element.leave(this, e.originalEvent);
}
}
};
Chart.prototype._start = function _start (e) {
var coords = this._eventCoordinates(e);
if (this._stopChartHandlers(e) || !this._plotArea.backgroundContainsPoint(coords)) {
return;
}
if (this.requiresHandlers([ DRAG_START, DRAG, DRAG_END ])) {
this._startNavigation(e, coords, DRAG_START);
}
if (this._pannable && this._pannable.start(e)) {
this.surface.suspendTracking();
this._unsetActivePoint();
this._clearFocusedElement();
this._suppressHover = true;
this.chartService.panning = true;
}
if (this._zoomSelection) {
if (this._zoomSelection.start(e)) {
this.trigger(ZOOM_START, { axisRanges: axisRanges(this._plotArea.axes), originalEvent: e });
}
}
};
Chart.prototype._move = function _move (e) {
var ref = this;
var state = ref._navState;
var pannable = ref._pannable;
if (this._stopChartHandlers(e)) {
return;
}
if (pannable) {
var ranges = pannable.move(e);
if (ranges && !this.trigger(DRAG, { axisRanges: ranges, originalEvent: e })) {
pannable.pan();
}
} else if (state) {
var ranges$1 = {};
var axes = state.axes;
for (var i = 0; i < axes.length; i++) {
var currentAxis = axes[i];
var axisName = currentAxis.options.name;
if (axisName) {
var axis = currentAxis.options.vertical ? e.y : e.x;
var delta = axis.startLocation - axis.location;
if (delta !== 0) {
ranges$1[currentAxis.options.name] = currentAxis.translateRange(delta);
}
}
}
state.axisRanges = ranges$1;
this.trigger(DRAG, {
axisRanges: ranges$1,
originalEvent: e
});
}
if (this._zoomSelection) {
this._zoomSelection.move(e);
}
};
Chart.prototype._end = function _end (e) {
if (this._stopChartHandlers(e)) {
return;
}
var pannable = this._pannable;
if (pannable && pannable.end(e)) {
this.surface.resumeTracking();
this.trigger(DRAG_END, {
axisRanges: axisRanges(this._plotArea.axes),
originalEvent: e
});
this._suppressHover = false;
this.chartService.panning = false;
} else {
this._endNavigation(e, DRAG_END);
}
if (this._zoomSelection) {
var ranges = this._zoomSelection.end(e);
if (ranges && !this.trigger(ZOOM, { axisRanges: ranges, originalEvent: e })) {
this._zoomSelection.zoom();
this.trigger(ZOOM_END, { axisRanges: ranges, originalEvent: e });
}
}
};
Chart.prototype._stopChartHandlers = function _stopChartHandlers (e) {
var selections = this._selections || [];
if (!selections.length) {
return false;
}
var coords = this._eventCoordinates(e);
var pane = this._plotArea.paneByPoint(coords);
if (pane) {
for (var idx = 0; idx < selections.length; idx++) {
if (selections[idx].onPane(pane)) {
return true;
}
}
}
};
Chart.prototype._mousewheelZoomRate = function _mousewheelZoomRate () {
var zoomable = this.options.zoomable;
var mousewheel = (zoomable || {}).mousewheel || {};
return valueOrDefault(mousewheel.rate, MOUSEWHEEL_ZOOM_RATE);
};
Chart.prototype._mousewheel = function _mousewheel (e) {
var this$1 = this;
var delta = mousewheelDelta(e);
var mousewheelZoom = this._mousewheelZoom;
var coords = this._eventCoordinates(e);
if (this._stopChartHandlers(e) || !this._plotArea.backgroundContainsPoint(coords)) {
return;
}
if (mousewheelZoom) {
var args = { delta: delta, axisRanges: axisRanges(this._plotArea.axes), originalEvent: e };
if (this._zooming || !this.trigger(ZOOM_START, args)) {
e.preventDefault();
if (!this._zooming) {
this._unsetActivePoint();
this._clearFocusedElement();
this.surface.suspendTracking();
this._zooming = true;
}
if (this._mwTimeout) {
clearTimeout(this._mwTimeout);
}
args.axisRanges = mousewheelZoom.updateRanges(delta, coords);
if (args.axisRanges && !this.trigger(ZOOM, args)) {
mousewheelZoom.zoom();
}
this._mwTimeout = setTimeout(function () {
this$1.trigger(ZOOM_END, args);
this$1._zooming = false;
if (this$1.surface) {
this$1.surface.resumeTracking();
}
}, MOUSEWHEEL_DELAY);
}
} else {
var state = this._navState;
if (!state) {
var prevented = this._startNavigation(e, coords, ZOOM_START);
if (!prevented) {
state = this._navState;
}
}
if (state) {
var totalDelta = state.totalDelta || delta;
state.totalDelta = totalDelta + delta;
var axes = this._navState.axes;
var ranges = {};
for (var i = 0; i < axes.length; i++) {
var currentAxis = axes[i];
var axisName = currentAxis.options.name;
if (axisName) {
ranges[axisName] = currentAxis.scaleRange(-totalDelta * this$1._mousewheelZoomRate(), coords);
}
}
this.trigger(ZOOM, {
delta: delta,
axisRanges: ranges,
originalEvent: e
});
if (this._mwTimeout) {
clearTimeout(this._mwTimeout);
}
this._mwTimeout = setTimeout(function () {
this$1._endNavigation(e, ZOOM_END);
}, MOUSEWHEEL_DELAY);
}
}
};
Chart.prototype._startNavigation = function _startNavigation (e, coords, chartEvent) {
var plotArea = this._model._plotArea;
var pane = plotArea.findPointPane(coords);
var axes = plotArea.axes.slice(0);
if (!pane) {
return;
}
var ranges = axisRanges(axes);
var prevented = this.trigger(chartEvent, {
axisRanges: ranges,
originalEvent: e
});
if (prevented) {
this._cancelDomEvents();
} else {
this._suppressHover = true;
this._unsetActivePoint();
this._clearFocusedElement();
this._navState = {
axisRanges: ranges,
pane: pane,
axes: axes
};
}
};
Chart.prototype._endNavigation = function _endNavigation (e, chartEvent) {
if (this._navState) {
this.trigger(chartEvent, {
axisRanges: this._navState.axisRanges,
originalEvent: e
});
this._suppressHover = false;
this._navState = null;
}
};
Chart.prototype._getChartElement = function _getChartElement (e, match) {
var element = this.surface.eventTarget(e);
if (element) {
return this._drawingChartElement(element, e, match);
}
};
Chart.prototype._drawingChartElement = function _drawingChartElement (element, e, match) {
var current = element;
var chartElement;
while (current && !chartElement) {
chartElement = current.chartElement;
current = current.parent;
}
if (chartElement) {
if (chartElement.aliasFor) {
chartElement = chartElement.aliasFor(e, this._eventCoordinates(e));
}
if (match) {
chartElement = chartElement.closest(match);
if (chartElement && chartElement.aliasFor) {
chartElement = chartElement.aliasFor();
}
}
return chartElement;
}
};
Chart.prototype._eventCoordinates = function _eventCoordinates (e) {
var coordinates = eventCoordinates(e);
return this._toModelCoordinates(coordinates.x, coordinates.y);
};
Chart.prototype._elementPadding = function _elementPadding () {
if (!this._padding) {
var ref = elementStyles(this.element, [ "paddingLeft", "paddingTop" ]);
var paddingLeft = ref.paddingLeft;
var paddingTop = ref.paddingTop;
this._padding = {
top: paddingTop,
left: paddingLeft
};
}
return this._padding;
};
Chart.prototype._toDocumentCoordinates = function _toDocumentCoordinates (point) {
var padding = this._elementPadding();
var offset = elementOffset(this.element);
return {
left: round(point.x + padding.left + offset.left),
top: round(point.y + padding.top + offset.top)
};
};
// TODO: Breaking change due to peer version change
// Reuse by exposing _surfacePoint on Surface
Chart.prototype._toModelCoordinates = function _toModelCoordinates (clientX, clientY) {
var element = this.element;
var offset = elementOffset(element);
var padding = this._elementPadding();
var inverseTransform = elementScale(element).invert();
var point = new geometry.Point(
clientX - offset.left - padding.left,
clientY - offset.top - padding.top
).transform(inverseTransform);
return new Point(point.x, point.y);
};
Chart.prototype._tap = function _tap (e) {
var this$1 = this;
var drawingElement = this.surface.eventTarget(e);
var element = this._drawingChartElement(drawingElement, e);
var sharedTooltip = this._sharedTooltip();
if (!this._startHover(drawingElement, e) && !sharedTooltip) {
this._unsetActivePoint();
}
if (sharedTooltip) {
this._trackSharedTooltip(this._eventCoordinates(e), e, true);
}
this._propagateClick(element, e);
//part of fix for hover issue on windows touch
this.handlingTap = true;
setTimeout(function () {
this$1.handlingTap = false;
}, 0);
};
Chart.prototype._click = function _click (e) {
var element = this._getChartElement(e);
this._propagateClick(element, e);
};
Chart.prototype._propagateClick = function _propagateClick (element, e) {
var this$1 = this;
var current = element;
while (current) {
if (current.click) {
current.click(this$1, e);
}
current = current.parent;
}
};
Chart.prototype._isLegendBeforeChart = function _isLegendBeforeChart () {
var ref = this;
var legendPosition = ref.options.legend.position;
var legend = ref._legend;
return legend && legend.hasItems() && (legendPosition === TOP || legendPosition === LEFT);
};
Chart.prototype._focus = function _focus () {
if (!this._preventInitialPointFocus) {
if (this._isLegendBeforeChart()) {
this._focusFirstLegendItem();
} else {
this._focusFirstPoint();
}
}
this._preventInitialPointFocus = false;
};
Chart.prototype._keydown = function _keydown (e) {
var ref = this;
var ref_focusState = ref._focusState;
var legendInFocus = ref_focusState.legendInFocus;
var focusedElement = ref_focusState.focusedElement;
var legend = ref._legend;
if (e.key === TAB) {
this._clearFocusedElement();
var isLegendBeforeChart = this._isLegendBeforeChart();
if (legendInFocus && isLegendBeforeChart !== e.shiftKey) {
this._navigatePoints(e);
} else if (!legendInFocus && isLegendBeforeChart === e.shiftKey && legend.hasItems()) {
this._navigateLegend(e);
}
} else if (e.key === ESCAPE) {
if (focusedElement) {
e.stopPropagation();
}
if (this._tooltip && this._tooltip.visible) {
this._hideTooltip();
} else {
this._blur();
}
} else if (e.key === ENTER) {
if (focusedElement) {
this._focusState.preserveHighlight = true;
this._propagateClick(focusedElement, e);
this._focusElement(focusedElement);
}
} else if (!legendInFocus) {
this._navigatePoints(e);
} else {
this._navigateLegend(e);
}
};
Chart.prototype._navigatePoints = function _navigatePoints (e) {
var this$1 = this;
var ref = this;
var focusState = ref._focusState;
var plotArea = ref._plotArea;
focusState.legendInFocus = false;
if (!focusState.focusedElement) {
this._focusFirstPoint();
e.preventDefault();
return;
}
var moveFocus = function (point) {
focusState.focusedPoint = point;
this$1._focusElement(focusState.focusedPoint);
this$1._displayTooltip(point);
e.preventDefault();
};
switch (e.key) {
case ARROW_RIGHT:
moveFocus(plotArea.getPointToTheRight(focusState.focusedPoint));
break;
case ARROW_LEFT:
moveFocus(plotArea.getPointToTheLeft(focusState.focusedPoint));
break;
case ARROW_DOWN:
moveFocus(plotArea.getPointBelow(focusState.focusedPoint));
break;
case ARROW_UP:
moveFocus(plotArea.getPointAbove(focusState.focusedPoint));
break;
default:
break;
}
};
Chart.prototype._navigateLegend = function _navigateLegend (e) {
var this$1 = this;
var ref = this;
var focusState = ref._focusState;
var legend = ref._legend;
var rtl = ref.chartService.rtl;
focusState.legendInFocus = true;
if (!focusState.focusedElement) {
this._focusFirstLegendItem();
e.preventDefault();
return;
}
var itemsLength = legend.getItems().length;
var moveFocus = function (cycleFunc) {
focusState.focusedLegendItemIndex = cycleFunc(
focusState.focusedLegendItemIndex,
itemsLength
);
this$1._focusElement(this$1._getFocusedLegendItem());
e.preventDefault();
};
switch (e.key) {
case ARROW_UP:
case ARROW_LEFT:
moveFocus(rtl ? cycleUp : cycleDown);
break;
case ARROW_DOWN:
case ARROW_RIGHT:
moveFocus(rtl ? cycleDown : cycleUp);
break;
default:
break;
}
};
Chart.prototype._focusFirstPoint = function _focusFirstPoint () {
var point = this._focusState.focusedPoint = this._plotArea.getFirstPoint();
if (point) {
this._focusElement(point);
this._displayTooltip(point);
}
};
Chart.prototype._hasFocus = function _hasFocus () {
return this.element.ownerDocument.activeElement === this.element;
};
Chart.prototype._mousedown = function _mousedown () {
if (!this._hasFocus()) {
this._preventInitialPointFocus = true;
}
};
Chart.prototype._focusChart = function _focusChart () {
if (!this._hasFocus()) {
this._preventInitialPointFocus = true;
this.element.focus();
}
};
Chart.prototype._focusPoint = function _focusPoint (point) {
this._focusState.focusedPoint = point;
this._focusChart();
this._focusElement(point, true);
};
Chart.prototype._focusFirstLegendItem = function _focusFirstLegendItem () {
var ref = this;
var focusState = ref._focusState;
focusState.focusedLegendItemIndex = 0;
this._focusElement(this._getFocusedLegendItem());
focusState.legendInFocus = true;
this._hideTooltip();
};
Chart.prototype._focusLegendItem = function _focusLegendItem (args) {
var ref = this;
var focusState = ref._focusState;
focusState.focusedLegendItemIndex = this._legend
.getItems()
.findIndex(function (x) { return x.options.series.index === args.seriesIndex
&& x.options.pointIndex === args.pointIndex; });
focusState.legendInFocus = true;
this._focusChart();
this._focusElement(this._getFocusedLegendItem(), true);
};
Chart.prototype._getFocusedLegendItem = function _getFocusedLegendItem () {
var ref = this;
var focusState = ref._focusState;
var legend = ref._legend;
return legend.getItems()[focusState.focusedLegendItemIndex];
};
Chart.prototype._focusElement = function _focusElement (element, omitHighlight) {
var ref = this;
var focusState = ref._focusState;
this._clearFocusedElement();
if (!element) {
return;
}
focusState.focusedElement = element;
this._setElementActiveDescendant(element);
if (!omitHighlight) {
element.focusVisual();
if (focusState.legendInFocus) {
var options = element.options;
this._showSeriesInactiveOpacity(options.series.index, options.pointIndex);
} else {
this._showInactiveOpacity(element);
}
}
};
Chart.prototype._clearFocusedElement = function _clearFocusedElement () {
var ref = this;
var focusState = ref._focusState;
if (!focusState) {
return;
}
if (focusState.focusedElement && focusState.focusedElement.clearFocusFromVisual) {
focusState.focusedElement.clearFocusFromVisual();
this._clearElementActiveDescendant();
}
focusState.focusedElement = null;
};
Chart.prototype._setElementActiveDescendant = function _setElementActiveDescendant (element) {
if (this.options.renderAs === "canvas") {
this._pseudoFocusedElement = this._createPseudoFocusedElement(element);
this.element.append(this._pseudoFocusedElement);
}
this.element.setAttribute(ARIA_ACTIVE_DESCENDANT, element._id);
};
Chart.prototype._clearElementActiveDescendant = function _clearElementActiveDescendant () {
if (this._pseudoFocusedElement) {
this._pseudoFocusedElement.remove();
this._pseudoFocusedElement = null;
}
this.element.removeAttribute(ARIA_ACTIVE_DESCENDANT);
};
Chart.prototype._createPseudoFocusedElement = function _createPseudoFocusedElement (element) {
var pseudoElement = document.createElement("div");
var accessibilityOptions = element.options.accessibility;
pseudoElement.id = element._id;
pseudoElement.setAttribute("aria-label"