UNPKG

@progress/kendo-ui

Version:

This package is part of the [Kendo UI for jQuery](http://www.telerik.com/kendo-ui) suite.

1,554 lines (1,280 loc) 53.6 kB
import './kendo.breadcrumb.js'; import './kendo.data.js'; import './kendo.dataviz.core.js'; import './kendo.dataviz.themes.js'; import './html-tvbcb-Oe.js'; import './kendo.userevents.js'; import './kendo.icons.js'; import * as chartExport from '@progress/kendo-charts/dist/es/chart-export.js'; import { DomEventsBuilder, InstanceObserver, defined, Chart, getField, SeriesBinder, grep, inArray } from '@progress/kendo-charts'; import './kendo.core.js'; import './kendo.html.icon.js'; import './kendo.html.base.js'; import '@progress/kendo-svg-icons'; import './kendo.data.odata.js'; import './kendo.data.xml.js'; import '@progress/kendo-charts/dist/es/core-export.js'; import './kendo.popup.js'; import '@progress/kendo-drawing'; import './kendo.color.js'; (function($, undefined$1) { const kendo = window.kendo; const dataviz = kendo.dataviz; const Widget = kendo.ui.Widget; const ChartBreadcrumb = Widget.extend({ init: function(element, options) { Widget.fn.init.call(this, element, options); if (!options.chart) { throw new Error('ChartBreadcrumb: No Chart instance supplied as `options.chart`'); } this._attachChartEvents(); this._renderBreadcrumb(); kendo.notify(this, dataviz.ui); }, events: [], options: { name: "ChartBreadcrumb", rootItem: { type: 'rootitem', icon: 'home', text: 'Home', showIcon: true } }, destroy: function() { if (this.breadcrumb) { this.breadcrumb.destroy(); this.breadcrumb = null; } if (this.chart) { this.chart.unbind('drilldown', this._onChartDrilldown); this.chart.unbind('drilldownLevelChange', this._onChartDrilldownLevelChange); this.chart = null; } Widget.fn.destroy.call(this); }, _attachChartEvents(deferred) { const options = this.options; if (typeof options.chart.resetDrilldownLevel === 'function') { this.chart = options.chart; } else if (typeof options.chart === 'string') { this.chart = $(options.chart).getKendoChart() || $('#' + options.chart).getKendoChart(); if (!this.chart && !deferred) { setTimeout(() => this._attachChartEvents(true)); return; } } else { throw new Error('ChartBreadcrumb: `options.chart` must be a Chart instance, element ID or a selector'); } this._onChartDrilldown = this._onChartDrilldown.bind(this); this.chart.bind('drilldown', this._onChartDrilldown); this._onChartDrilldownLevelChange = this._onChartDrilldownLevelChange.bind(this); this.chart.bind('drilldownLevelChange', this._onChartDrilldownLevelChange); }, _renderBreadcrumb: function() { const breadcrumbElement = $('<nav />'); this.element.append(breadcrumbElement); this.breadcrumb = new kendo.ui.Breadcrumb(breadcrumbElement, { items: [this.options.rootItem] }); this.breadcrumb.bind('click', e => this._onBreadcrumbClick(e)); }, _onBreadcrumbClick: function(e) { if (!this.breadcrumb || !this.chart) { return; } let items = this.breadcrumb.items(); const level = items.findIndex((item) => item === e.item); const chart = this.chart; chart.resetDrilldownLevel(level); }, _onChartDrilldown: function(e) { if (!this.breadcrumb || e.isDefaultPrevented()) { return; } this.breadcrumb.items([ ...this.breadcrumb.items(), { type: 'item', text: e.point.category } ]); }, _onChartDrilldownLevelChange: function(e) { if (!this.breadcrumb) { return; } let items = this.breadcrumb.items(); items = items.slice(0, e.level + 1); this.breadcrumb.items(items); } }); dataviz.ui.plugin(ChartBreadcrumb); })(window.kendo.jQuery); const __meta__ = { id: "dataviz.chart", name: "Chart", category: "dataviz", description: "The Chart widget uses modern browser technologies to render high-quality data visualizations in the browser.", depends: [ "data", "userevents", "drawing", "dataviz.core", "dataviz.themes", "breadcrumb" ], features: [{ id: "dataviz.chart-pdf-export", name: "PDF export", description: "Export Chart as PDF", depends: [ "pdf" ] }] }; (function($, undefined$1) { var kendo = window.kendo; kendo.dataviz = kendo.dataviz || {}; kendo.deepExtend(kendo.dataviz, kendo.deepExtend({}, chartExport)); var NS = ".kendoChart"; var Class = kendo.Class; var outerWidth = kendo._outerWidth; var outerHeight = kendo._outerHeight; var dataviz = kendo.dataviz; var Widget = kendo.ui.Widget; var DataSource = kendo.data.DataSource; var deepExtend = kendo.deepExtend; var isArray = Array.isArray; var extend = $.extend; var template = kendo.template; var encode = kendo.htmlEncode; var MOUSELEAVE_NS = "mouseleave" + NS; var constants = chartExport.constants; var AXIS_LABEL_CLICK = "axisLabelClick"; var LEGEND_ITEM_CLICK = constants.LEGEND_ITEM_CLICK; var LEGEND_ITEM_HOVER = constants.LEGEND_ITEM_HOVER; var LEGEND_ITEM_LEAVE = constants.LEGEND_ITEM_LEAVE; var SERIES_CLICK = constants.SERIES_CLICK; var SERIES_HOVER = constants.SERIES_HOVER; var SERIES_OVER = constants.SERIES_OVER; var SERIES_LEAVE = constants.SERIES_LEAVE; var PANE_RENDER = constants.PANE_RENDER; var PLOT_AREA_CLICK = constants.PLOT_AREA_CLICK; var PLOT_AREA_HOVER = constants.PLOT_AREA_HOVER; var PLOT_AREA_LEAVE = constants.PLOT_AREA_LEAVE; var DRAG = constants.DRAG; var DRAG_END = constants.DRAG_END; var DRAG_START = constants.DRAG_START; var DRILLDOWN = constants.DRILLDOWN; var DRILLDOWN_LEVEL_CHANGE = "drilldownLevelChange"; var ZOOM_START = constants.ZOOM_START; var ZOOM = constants.ZOOM; var ZOOM_END = constants.ZOOM_END; var SELECT_START = constants.SELECT_START; var SELECT = constants.SELECT; var SELECT_END = constants.SELECT_END; var RENDER = constants.RENDER; var NOTE_CLICK = "noteClick"; var NOTE_HOVER = "noteHover"; var NOTE_LEAVE = "noteLeave"; var DOCUMENT_ELEMENT = $(document.documentElement); var CHANGE = "change"; var DATABOUND = "dataBound"; var LEAVE = "leave"; var MOUSEDOWN = "down"; var VALUE = "value"; var PIE = constants.PIE; var DONUT = constants.DONUT; var FUNNEL = constants.FUNNEL; var Observable = kendo.Observable; var TOOLTIP_ANIMATION_DURATION = 150; var TOOLTIP_SHOW_DELAY = 100; var TOOLTIP_INVERSE = "k-chart-tooltip-inverse"; var SHARED_TOOLTIP_CLASS = "k-chart-shared-tooltip"; var RTL = "rtl"; DomEventsBuilder.register({ create: function(element, events) { return new kendo.UserEvents(element, deepExtend({ global: true, multiTouch: true, fastTap: true }, events)); } }); let ConvertedObserver = kendo.ConvertClass(InstanceObserver); var ChartInstanceObserver = ConvertedObserver.extend({ handlerMap: { showTooltip: '_showTooltip', hideTooltip: '_hideTooltip', legendItemClick: '_onLegendItemClick', render: '_onRender', init: '_onInit', drilldown: '_onDrilldown' } }); var Chart$1 = Widget.extend({ init: function(element, userOptions) { var dataSource; kendo.destroy(element); Widget.fn.init.call(this, element); if (userOptions) { dataSource = userOptions.dataSource; delete userOptions.dataSource; } this.options = deepExtend({}, this.options, userOptions); this.wrapper = this.element; this._attachEvents(); if (userOptions) { userOptions.dataSource = dataSource; } this._seriesVisibility = new SeriesVisibilityState(); this.bind(this.events, this.options); this._initDataSource(userOptions); this._drilldownState = []; kendo.notify(this, dataviz.ui); if (this._showWatermarkOverlay) { this._showWatermarkOverlay(this.wrapper[0]); } }, events: [ DATABOUND, DRILLDOWN, DRILLDOWN_LEVEL_CHANGE, SERIES_CLICK, SERIES_HOVER, SERIES_OVER, SERIES_LEAVE, AXIS_LABEL_CLICK, LEGEND_ITEM_CLICK, LEGEND_ITEM_HOVER, LEGEND_ITEM_LEAVE, PANE_RENDER, PLOT_AREA_CLICK, PLOT_AREA_HOVER, PLOT_AREA_LEAVE, DRAG_START, DRAG, DRAG_END, ZOOM_START, ZOOM, ZOOM_END, SELECT_START, SELECT, SELECT_END, NOTE_CLICK, NOTE_HOVER, NOTE_LEAVE, RENDER ], options: { name: "Chart", renderAs: "", theme: "sass", axisDefaults: {}, chartArea: {}, legend: {}, categoryAxis: {}, autoBind: true, seriesDefaults: {}, series: [], seriesColors: null, tooltip: {}, transitions: true, valueAxis: {}, plotArea: {}, title: {}, xAxis: {}, yAxis: {}, panes: [{}], pannable: false, zoomable: false, noData: true, messages: { noData: "No data available" } }, items: function() { return $(); }, refresh: function() { var chart = this; var instance = chart._instance; instance.applyDefaults(chart.options); instance.applySeriesColors(); chart._bindSeries(); chart._bindCategories(); chart.trigger(DATABOUND); chart._redraw(); }, getSize: function() { return kendo.dimensions(this.element); }, redraw: function(paneName) { this._size = null; this._instance.redraw(paneName); }, setOptions: function(options) { var chart = this, dataSource = options.dataSource; delete options.dataSource; Widget.fn._setEvents.call(chart, options); this._instance.applyOptions(options, this._getThemeOptions(options)); this.options = this._instance.options; this._tooltip.setOptions(this.options.tooltip); this._seriesVisibility.setOptions(this.options); this._sourceSeries = null; if (dataSource) { chart.setDataSource(dataSource); } if (chart._hasDataSource) { chart._onDataChanged(); } else { chart._bindCategories(); chart.redraw(); } chart._instance.updateMouseMoveHandler(); }, setDataSource: function(dataSource) { var chart = this; chart.dataSource.unbind(CHANGE, chart._dataChangeHandler); chart.dataSource = dataSource = DataSource.create(dataSource); chart._hasDataSource = true; chart._hasData = false; dataSource.bind(CHANGE, chart._dataChangeHandler); if (chart.options.autoBind) { dataSource.fetch(); } }, destroy: function() { var chart = this, dataSource = chart.dataSource; chart.element.off(NS); if (dataSource) { dataSource.unbind(CHANGE, chart._dataChangeHandler); } if (chart._instance) { chart._instance.destroy(); delete this._instance; } if (this._tooltip) { this._tooltip.destroy(); delete this._tooltip; } this._destroyNoData(); this._destroyCrosshairTooltips(); Widget.fn.destroy.call(chart); }, findPaneByName: function(name) { var panes = this._plotArea.panes; for (var idx = 0; idx < panes.length; idx++) { if (panes[idx].options.name === name) { return new ChartPane(this, panes[idx]); } } }, findPaneByIndex: function(idx) { var panes = this._plotArea.panes; if (panes[idx]) { return new ChartPane(this, panes[idx]); } }, findSeries: function(callback) { var plotArea = this._plotArea; var series = plotArea.srcSeries || plotArea.series; for (var idx = 0; idx < series.length; idx++) { if (callback(series[idx])) { return new ChartSeries(this, series[idx]); } } }, findSeriesByName: function(name) { return this._createSeries({ name: name }); }, findSeriesByIndex: function(index) { return this._createSeries({ index: index }); }, exportVisual: function(options) { var instance = this._instance; if (!instance) { return; } var visual; //TO DO: support for setting any options. already available in kendo-charts if (options && (options.width || options.height)) { var chartArea = instance.options.chartArea; var originalChartArea = instance._originalOptions.chartArea; deepExtend(chartArea, options); var model = instance._getModel(); chartArea.width = originalChartArea.width; chartArea.height = originalChartArea.height; model.renderVisual(); triggerPaneRender(model._plotArea.panes); visual = model.visual; } else { visual = instance.exportVisual(); } return visual; }, resetDrilldownLevel(level) { level = level || 0; const state = this._drilldownState; if (!state || level < 0 || level > state.length - 1) { return; } const args = { level, sender: this }; this.trigger(DRILLDOWN_LEVEL_CHANGE, args); this.options.series = this._drilldownState[level]; this._drilldownState = this._drilldownState.slice(0, level); this._bindCategories(); this._redraw(); }, _createSeries: function(options) { var seriesOptions = this._seriesOptions(options); if (seriesOptions) { return new ChartSeries(this, seriesOptions); } }, _seriesOptions: function(options) { var plotArea = this._plotArea; var series = plotArea.srcSeries || plotArea.series; var seriesOptions; if (defined(options.index)) { seriesOptions = series[options.index]; } else if (defined(options.name)) { for (var idx = 0; idx < series.length; idx++) { if (series[idx].name === options.name) { seriesOptions = series[idx]; break; } } } return seriesOptions; }, _attachEvents: function() { this.element.on(MOUSELEAVE_NS, this._mouseleave.bind(this)); }, _mouseleave: function(e) { var instance = this._instance; var tooltip = this._tooltip; var target = e.relatedTarget; if (!(target && $(target).closest(tooltip.element).length) && instance && !instance.handlingTap) { instance.hideElements({ keepTooltipOpen: !tooltip.options.autoHide }); } }, _getThemeOptions: function(userOptions) { var themeName = (userOptions || {}).theme; if (themeName && dataviz.SASS_THEMES.indexOf(themeName.toLowerCase()) !== -1) { return dataviz.autoTheme().chart; } if (defined(themeName)) { var themes = dataviz.ui.themes || {}; var theme = themes[themeName] || themes[themeName.toLowerCase()] || {}; return theme.chart || {}; } }, _initChart: function() { this._createChart(this.options, this._getThemeOptions(this.options)); this.options = this._instance.options; this._seriesVisibility.setOptions(this.options); }, _createChart: function(options, themeOptions) { this._instance = new Chart(this.element[0], options, themeOptions, { observer: new InstanceObserver(this, { showTooltip: '_showTooltip', hideTooltip: '_hideTooltip', legendItemClick: '_onLegendItemClick', render: '_onRender', init: '_onInit', drilldown: '_onDrilldown' }), sender: this, rtl: this._isRtl() }); }, _onInit: function(e) { this._instance = e.sender; }, _initDataSource: function(userOptions) { var chart = this, dataSource = (userOptions || {}).dataSource; chart._dataChangeHandler = chart._onDataChanged.bind(chart); chart.dataSource = DataSource .create(dataSource) .bind("change", chart._dataChangeHandler); chart._bindCategories(); if (dataSource) { chart._hasDataSource = true; } this._initNoData(); this._initChart(); this._initTooltip(); if (dataSource) { if (chart.options.autoBind) { chart.dataSource.fetch(); } } }, _destroyCrosshairTooltips: function() { var tooltips = this._crosshairTooltips; if (tooltips) { for (var key in tooltips) { tooltips[key].destroy(); } } this._crosshairTooltips = {}; }, _getCrosshairTooltip: function(name, index) { var tooltips = this._crosshairTooltips = this._crosshairTooltips || {}; var key = name + index; var tooltip = tooltips[key]; if (!tooltip) { tooltip = tooltips[key] = new CrosshairTooltip(this.element); } return tooltip; }, _showTooltip: function(e) { if (e.crosshair) { var tooltip = this._getCrosshairTooltip(e.axisName, e.axisIndex); tooltip.show(e); } else if (this._tooltip) { this._tooltip.show(e); } }, _hideTooltip: function(e) { if (e.crosshair) { var tooltip = this._getCrosshairTooltip(e.axisName, e.axisIndex); tooltip.hide(); } else if (this._tooltip) { this._tooltip.hide(); } }, _onRender: function(e) { this._destroyCrosshairTooltips(); this._copyMembers(e.sender); if (!this._hasDataSource || this._hasData || !this.options.autoBind) { this.trigger(RENDER); } }, _copyMembers: function(instance) { this.options = instance.options; this._originalOptions = instance._originalOptions; this.surface = instance.surface; this._plotArea = instance._plotArea; this._model = instance._model; this._highlight = instance._highlight; this._selections = instance._selections; this._pannable = instance._pannable; this._zoomSelection = instance._zoomSelection; this._mousewheelZoom = instance._mousewheelZoom; }, requiresHandlers: function(names) { var events = this._events; for (var idx = 0; idx < names.length; idx++) { if (defined(events[names[idx]])) { return true; } } }, _initTooltip: function() { this._tooltip = this._createTooltip(); this._tooltip.bind(LEAVE, this._tooltipleave.bind(this)); }, _onLegendItemClick: function(e) { if (!this.trigger(LEGEND_ITEM_CLICK, e)) { this._legendItemClick(e.seriesIndex, e.pointIndex); } }, _legendItemClick: function(seriesIndex, pointIndex) { var chart = this._instance, plotArea = chart._plotArea, currentSeries = (plotArea.srcSeries || plotArea.series)[seriesIndex]; if (chart._hasInactiveOpacity() && chart._activeChartInstance) { chart._updateSeriesOpacity(null, true); chart._applySeriesOpacity(chart._activeChartInstance.children, null, true); chart._activeChartInstance = null; } if ($.inArray(currentSeries.type, [PIE, DONUT, FUNNEL]) >= 0) { var point = currentSeries.data[pointIndex]; if (point && defined(point.visible)) { point.visible = !point.visible; } else { var pointVisibility = currentSeries.pointVisibility = currentSeries.pointVisibility || {}; var visible = pointVisibility[pointIndex]; pointVisibility[pointIndex] = defined(visible) ? !visible : false; } } else { currentSeries.visible = !currentSeries.visible; this._seriesVisibility.save(currentSeries); } chart._noTransitionsRedraw(); }, _createTooltip: function() { return new Tooltip(this.element, extend({}, this.options.tooltip, { rtl: this._isRtl() })); }, _tooltipleave: function() { if (this._instance) { this._instance.hideElements(); } }, _onDrilldown: function(e) { const { series, value } = e; if (series.drilldownSeriesFactory) { const result = series.drilldownSeriesFactory(value); if (!result) { return; } else if (result instanceof Promise) { result.then((resolved) => this._onDrilldownData(e, resolved)); } else { this._onDrilldownData(e, result); } } else if (typeof value === 'object') { this._onDrilldownData(e, value); } }, _onDrilldownData: function(e, data) { const drilldownSeries = Object.assign({}, e.series, data); const args = { point: e.point, series: e.series, drilldownSeries, sender: this }; const prevented = this.trigger(DRILLDOWN, args); if (!prevented) { this._drilldownState.push(this.options.series); this.options.series = [drilldownSeries]; this._bindCategories(); this._redraw(); } }, _bindData: function(e) { var chart = this, options = chart.options, series = chart._sourceSeries || options.series, seriesIx, seriesLength = series.length, data = chart.dataSource.view(), grouped = (chart.dataSource.group() || []).length > 0, processedSeries = [], seriesVisibility = this._seriesVisibility, currentSeries, groupedSeries; seriesVisibility.read(); for (seriesIx = 0; seriesIx < seriesLength; seriesIx++) { currentSeries = series[seriesIx]; if (chart._isBindable(currentSeries) && grouped) { groupedSeries = groupSeries(currentSeries, data); processedSeries = processedSeries.concat(groupedSeries); seriesVisibility.applyByGroup(groupedSeries, e); } else { currentSeries = extend({}, currentSeries); processedSeries.push(currentSeries); seriesVisibility.applyByIndex(currentSeries, e); } } chart._sourceSeries = series; options.series = processedSeries; this._instance.applySeriesColors(); chart._bindSeries(); chart._bindCategories(); this._hasData = true; }, _initNoData: function() { if (this._noData || this.options.noData === false) { return; } const noDataWrap = $("<div class='k-chart-overlay'></div>"); this._noData = noDataWrap.hide().appendTo(this.wrapper); const noDataContent = $("<div class='k-no-data'></div>"); noDataContent.appendTo(this._noData); const template = this.options.noData?.template || (() => encode(this.options.messages.noData)); if (template) { const templateFn = typeof template !== "function" ? kendo.template(template) : template; noDataContent.html(templateFn({})); } }, _destroyNoData: function() { if (this._noData) { kendo.destroy(this._noData); this._noData.remove(); delete this._noData; delete this._noDataContent; } }, _onDataChanged: function(e) { this._bindData(e); // If there is data in the dataSource, remove the no data overlay. if (this.dataSource.total() > 0) { this._destroyNoData(); } this.trigger(DATABOUND); if (this._instance && this._instance.fontLoaded) { this._redraw(); } }, _bindSeries: function() { var chart = this, data = chart.dataSource.view(), series = chart.options.series, seriesIx, seriesLength = series.length, currentSeries, groupIx, seriesData; for (seriesIx = 0; seriesIx < seriesLength; seriesIx++) { currentSeries = series[seriesIx]; if (chart._isBindable(currentSeries)) { groupIx = currentSeries._groupIx; seriesData = defined(groupIx) ? (data[groupIx] || {}).items : data; if (currentSeries.autoBind !== false) { currentSeries.data = seriesData; } } } }, _bindCategories: function() { var chart = this, data = chart.dataSource.view() || [], grouped = (chart.dataSource.group() || []).length > 0, categoriesData = data, options = chart.options, definitions = [].concat(options.categoryAxis), axisIx, axis; if (grouped) { if (data.length) { categoriesData = data[0].items; } } for (axisIx = 0; axisIx < definitions.length; axisIx++) { axis = definitions[axisIx]; if (axis.autoBind !== false) { chart._bindCategoryAxis(axis, categoriesData, axisIx); } } }, _bindCategoryAxis: function(axis, data, axisIx) { var count = (data || []).length, categoryIx, category, row; if (axis.field) { axis.categories = []; for (categoryIx = 0; categoryIx < count; categoryIx++) { row = data[categoryIx]; category = getField(axis.field, row); if (categoryIx === 0) { axis.categories = [category]; axis.dataItems = [row]; } else { axis.categories.push(category); axis.dataItems.push(row); } } } else if (this._instance) { this._instance.bindCategoryAxisFromSeries(axis, axisIx); } }, _isBindable: function(series) { var valueFields = SeriesBinder.current.valueFields(series), result = true, field, i; for (i = 0; i < valueFields.length; i++) { field = valueFields[i]; if (field === VALUE) { field = "field"; } else { field = field + "Field"; } if (!defined(series[field])) { result = false; break; } } return result; }, _isRtl: function() { return kendo.support.isRtl(this.element) && this.element.css("direction") === RTL; } }); var proxyMembers = ["getAxis", "findAxisByName", "plotArea", "toggleHighlight", "showTooltip", "hideTooltip", "_resize", "_redraw", "_noTransitionsRedraw", "_legendItemHover", "_eventCoordinates"]; function createProxyMember(name) { Chart$1.fn[name] = function() { var instance = this._instance; if (instance) { return instance[name].apply(instance, arguments); } }; } for (var idx = 0; idx < proxyMembers.length; idx++) { createProxyMember(proxyMembers[idx]); } function groupSeries(series, data) { var result = [], nameTemplate, legacyTemplate = series.groupNameTemplate, groupIx, dataLength = data.length, seriesClone, defaultNameTemplate = ({ group }) => `${defined(series.name) ? group.value + ": " + series.name : group.value}`; if (dataLength === 0) { seriesClone = deepExtend({}, series); seriesClone.visibleInLegend = false; return [seriesClone]; } if (defined(legacyTemplate)) { kendo.logToConsole( "'groupNameTemplate' is obsolete and will be removed in future versions. " + "Specify the group name template as 'series.name'" ); if (legacyTemplate) { nameTemplate = template(legacyTemplate); } } else { nameTemplate = template(series.name || defaultNameTemplate); } for (groupIx = 0; groupIx < dataLength; groupIx++) { seriesClone = deepExtend({}, series); if (!kendo.isFunction(seriesClone.color)) { seriesClone.color = undefined$1; } seriesClone._groupIx = groupIx; seriesClone._groupValue = data[groupIx].value; result.push(seriesClone); if (nameTemplate) { seriesClone.name = nameTemplate({ series: seriesClone, group: data[groupIx] }); } } return result; } dataviz.ExportMixin.extend(Chart$1.fn); if (kendo.PDFMixin) { kendo.PDFMixin.extend(Chart$1.fn); } dataviz.ui.plugin(Chart$1); var SeriesVisibilityState = Class.extend({ init: function() { this.groups = {}; this.index = {}; this.options = {}; }, applyByGroup: function(series, e) { if ((e && e.action) || this.options.persistSeriesVisibility) { for (var idx = 0; idx < series.length; idx++) { if (this.groups[series[idx]._groupValue] === false) { series[idx].visible = false; } } } else { this.groups = {}; } }, applyByIndex: function(series, e) { if ((e && e.action) || this.options.persistSeriesVisibility) { if (this.index[series.index] === false) { series.visible = false; } } else { this.index = {}; } }, save: function(series) { if (!series) { return; } if (this.options.persistSeriesVisibility) { this.options.series[series.index].visible = series.visible; } else { this.saveState(series); } }, setOptions: function(options) { this.options = options; this.groups = {}; this.index = {}; }, read: function() { var options = this.options; if (options.persistSeriesVisibility) { var series = options.series; for (var idx = 0; idx < series.length; idx++) { this.saveState(series[idx]); } } }, saveState: function(series) { if (defined(series._groupValue)) { this.groups[series._groupValue] = series.visible; } else { this.index[series.index] = series.visible; } } }); var geom = kendo.geometry; function normalizeStyle(style) { for (var field in style) { if (style[field] === undefined$1) { style[field] = ''; } } return style; } var Tooltip = Observable.extend({ init: function(chartElement, options) { var tooltip = this; Observable.fn.init.call(tooltip); this.setOptions(options); tooltip.chartElement = chartElement; tooltip.template = Tooltip.template; if (!tooltip.template) { tooltip.template = Tooltip.template = ({ autoHide, rtl, font, border, opacity }) => `<div class='k-tooltip ${autoHide ? "k-tooltip-closable" : ""} k-chart-tooltip ${rtl ? "k-rtl" : ""}' ` + `${kendo.attr("style-display")}="none" ${kendo.attr("style-position")}="absolute" ` + `${kendo.attr("style-font")}="${font}" ${kendo.attr("style-opacity")}="${opacity}" ` + `${border ? `${kendo.attr("style-border")}="${border.width}px solid" ` : ""}` + `>` + '<div class="k-tooltip-content"></div>' + `${autoHide ? '' : '<div class="k-tooltip-button">' + kendo.ui.icon($('<a href="#" title="Close"></a>'), { icon: "x" }) + '</div>'}` + "</div>"; } tooltip.element = $(tooltip.template(tooltip.options)); kendo.applyStylesFromKendoAttributes(tooltip.element, ["display", "position", "font", "border", "opacity"]); tooltip.move = tooltip.move.bind(tooltip); tooltip._mouseleave = tooltip._mouseleave.bind(tooltip); var mobileScrollerSelector = kendo.format("[{0}='content'],[{0}='scroller']", kendo.attr("role")); tooltip._mobileScroller = chartElement.closest(mobileScrollerSelector).data("kendoMobileScroller"); tooltip.downEvent = kendo.applyEventMap(MOUSEDOWN, kendo.guid()); tooltip._closeTooltipHandler = tooltip._closeTooltip.bind(tooltip); }, destroy: function() { var tooltip = this; this._clearShowTimeout(); DOCUMENT_ELEMENT.off(tooltip.downEvent, tooltip._closeTooltipHandler); if (this.element) { this.element.off(MOUSELEAVE_NS).remove(); this.element = null; } }, setOptions: function(options) { this.options = deepExtend({}, this.options, options); }, options: { opacity: 1, animation: { duration: TOOLTIP_ANIMATION_DURATION }, sharedTemplate: ({ colspan, categoryText, points, content, colorMarker, nameColumn }) => "<table>" + `<th colspan='${colspan}'>${categoryText}</th>` + sharedTemplateIterator(points, colorMarker, nameColumn, content) + "</table>", categoryFormat: "{0:d}", autoHide: true }, move: function() { var tooltip = this, options = tooltip.options, element = tooltip.element, offset; if (!tooltip.anchor || !tooltip.element) { return; } offset = tooltip._offset(); if (!tooltip.visible) { element.css({ top: offset.top, left: offset.left }); } tooltip.visible = true; tooltip._ensureElement(document.body); element .stop(true, true) .show() .animate({ left: offset.left, top: offset.top }, options.animation.duration); }, _clearShowTimeout: function() { if (this.showTimeout) { clearTimeout(this.showTimeout); this.showTimeout = null; } }, getAnchor: function(size) { var anchor = this.anchor; var point = anchor.point; var align = anchor.align; var x = point.left; var y = point.top; if (align.horizontal === "center") { x -= size.width / 2; } else if (align.horizontal === "right") { x -= size.width; } if (align.vertical === "center") { y -= size.height / 2; } else if (align.vertical === "bottom") { y -= size.height; } return { x: x, y: y }; }, _offset: function() { var tooltip = this, size = tooltip._measure(), anchor = tooltip.getAnchor(size), top = anchor.y, left = anchor.x, zoomLevel = kendo.support.zoomLevel(), viewport = $(window), scrollTop = window.pageYOffset || document.documentElement.scrollTop || 0, scrollLeft = window.pageXOffset || document.documentElement.scrollLeft || 0, movable = (this._mobileScroller || {}).movable; if (!movable || movable.scale === 1) { top += tooltip._fit(top - scrollTop, size.height, outerHeight(viewport) / zoomLevel); left += tooltip._fit(left - scrollLeft, size.width, outerWidth(viewport) / zoomLevel); } else { var transform = geom.transform().scale(movable.scale, movable.scale, [movable.x, movable.y]); var point = new geom.Point(left, top).transform(transform); left = point.x; top = point.y; } return { top: top, left: left }; }, show: function(e) { var tooltip = this; var fakeContainer = $("<div></div>"); this.anchor = e.anchor; this.element.css(normalizeStyle(e.style)); this.element.toggleClass(TOOLTIP_INVERSE, !!e.className); this.element.toggleClass(SHARED_TOOLTIP_CLASS, !!e.shared); var content = e.shared ? this._sharedContent(e) : this._pointContent(e.point); fakeContainer.html(content); kendo.applyStylesFromKendoAttributes(fakeContainer, ["background-color"]); this.element.find('.k-tooltip-content').empty().append(fakeContainer); if (!tooltip.options.autoHide) { tooltip.element.off("click" + NS).on("click" + NS, ".k-tooltip-button", tooltip._closeTooltipHandler); DOCUMENT_ELEMENT.off(tooltip.downEvent, tooltip._closeTooltipHandler) .on(tooltip.downEvent, tooltip._closeTooltipHandler); } this._clearShowTimeout(); this.showTimeout = setTimeout(this.move, TOOLTIP_SHOW_DELAY); }, hide: function(forceHide) { var tooltip = this; if (!tooltip.options.autoHide && !forceHide) { return; } clearTimeout(tooltip.showTimeout); tooltip._hideElement(); if (tooltip.visible) { tooltip.point = null; tooltip.visible = false; tooltip.index = null; DOCUMENT_ELEMENT.off(tooltip.downEvent, tooltip._closeTooltipHandler); } }, _closeTooltip: function(e) { var target = $(e.target); if (!target.is(".k-chart-tooltip, .k-tooltip-content")) { e.preventDefault(); this.chartElement.data("kendoChart")._instance.hideElements(); this.hide(true); } }, _sharedContent: function(e) { var points = e.points; var that = this; var nameColumn = grep(points, function(point) { return defined(point.series.name); }).length; var colorMarker = e.series.length > 1; var colspan = 1; if (nameColumn) { colspan++; } if (colorMarker) { colspan++; } var template = kendo.template(this.options.sharedTemplate); var content = template({ points: points, category: e.category, categoryText: e.categoryText, content: this._pointContent.bind(that), colorMarker: colorMarker, nameColumn: nameColumn, colspan: colspan }); return content; }, _measure: function() { this._ensureElement(); var size = { width: outerWidth(this.element), height: outerHeight(this.element) }; return size; }, _ensureElement: function() { if (this.element) { this.element .appendTo(document.body) .on(MOUSELEAVE_NS, this._mouseleave); } }, _mouseleave: function(e) { var target = e.relatedTarget; var chart = this.chartElement[0]; if (target && target !== chart && !$.contains(chart, target)) { this.trigger(LEAVE); } }, _hideElement: function() { var tooltip = this; var element = this.element; if (element) { element.fadeOut({ always: function() { if (!tooltip.visible) { element.off(MOUSELEAVE_NS).remove(); } } }); } }, _pointContent: function(point) { var tooltip = this, options = deepExtend({}, tooltip.options, point.options.tooltip), content, tooltipTemplate; if (defined(point.value)) { content = point.value.toString(); } if (options.template) { tooltipTemplate = template(options.template); content = tooltipTemplate({ value: point.value, category: point.category, series: point.series, dataItem: point.dataItem, percentage: point.percentage, runningTotal: point.runningTotal, total: point.total, low: point.low, high: point.high, xLow: point.xLow, xHigh: point.xHigh, yLow: point.yLow, yHigh: point.yHigh }); } else if (options.format) { content = point.formatValue(options.format); } return content; }, _fit: function(offset, size, viewPortSize) { var output = 0; if (offset + size > viewPortSize) { output = viewPortSize - (offset + size); } if (offset < 0) { output = -offset; } return output; } }); var CrosshairTooltip = Tooltip.extend({ init: function(chartElement, options) { Tooltip.fn.init.call(this, chartElement, options); this.element.addClass("k-chart-crosshair-tooltip"); }, show: function(e) { var element = this.element; if (element) { this.anchor = e.anchor; this.element.css(e.style); this.element.html(this.content(e)); this.move(); } }, move: function() { var tooltip = this, element = tooltip.element, offset = tooltip._offset(); tooltip._ensureElement(); element.css({ top: offset.top, left: offset.left }).show(); }, content: function(e) { var content = e.value, options = e.crosshair.options.tooltip; if (options.template) { content = template(options.template)({ value: content }); } return content; }, hide: function() { this.element.hide(); } }); var ChartPane = Class.extend({ init: function(chart, pane) { this._chart = chart; this._pane = pane; this.visual = pane.visual; this.chartsVisual = pane.chartContainer.visual; this.name = pane.options.name; }, series: function() { var chart = this._chart; var seriesByPane = chart._plotArea.groupSeriesByPane(); var series = seriesByPane[this.name || "default"]; var result = []; if (series) { for (var idx = 0; idx < series.length; idx++) { result.push(new ChartSeries(chart, series[idx])); } } return result; } }); var ChartSeries = Class.extend({ init: function(chart, options) { this._chart = chart; this._options = options; }, points: function(filter) { var points = this._points; if (!points) { var series = this._seriesOptions(); var plotArea = this._chart._plotArea; this._points = points = plotArea.pointsBySeriesIndex(series.index); } if (kendo.isFunction(filter)) { points = this._filterPoints(points, filter); } return points; }, data: function(data) { var series = this._seriesOptions(); if (data) { var chart = this._chart; var plotArea = chart._plotArea; series.data = data; if (series.categoryField) { var axis = plotArea.seriesCategoryAxis(series); var options = [].concat(chart.options.categoryAxis); chart._instance.bindCategoryAxisFromSeries(options[axis.axisIndex], axis.axisIndex); } chart._noTransitionsRedraw(); this._clearFields(); } return series.data; }, findPoint: function(filter) { var points = this.points(); for (var idx = 0; idx < points.length; idx++) {