UNPKG

@highcharts/dashboards

Version:
219 lines (218 loc) 9.91 kB
/* * * * (c) 2009-2026 Highsoft AS * * Integration of this software requires a license. * - For commercial use, see www.highcharts.com/license * - For non-commercial, see www.highcharts.com/license-eula * * * Authors: * - Dawid Draguła * * */ 'use strict'; import { addEvent, isString } from '../../../../Shared/Utilities.js'; /* * * * Constants * * */ const defaultOptions = {}; const syncPair = { emitter: function () { if (this.type !== 'Highcharts') { return; } const component = this; const cleanupCallbacks = []; const { chart, board } = component; const connector = component.connectorHandlers?.[0]?.connector; const table = connector && connector.getTable(); const syncOptions = this.sync.syncConfig.extremes; const groupKey = syncOptions.group ? ':' + syncOptions.group : ''; const { dataCursor: cursor } = board; if (table && chart) { const extremesEventHandler = (e) => { const reset = !!e.resetSelection; if ((!e.trigger || (e.trigger && e.trigger !== 'dashboards-sync')) && !reset) { // TODO: investigate this type? const axis = e.target; const seriesFromConnectorArray = Object.keys(component.seriesFromConnector); // Prefer a series that's in a related table, // but allow for other data const series = seriesFromConnectorArray.length > 0 ? chart.get(seriesFromConnectorArray[0]) : axis.series[0]; if (series) { // Get the indexes of the first and last drawn points const visiblePoints = series.points.filter((point) => point.isInside || false); const minCursorData = { type: 'position', state: `${axis.coll}.extremes.min${groupKey}` }; const maxCursorData = { type: 'position', state: `${axis.coll}.extremes.max${groupKey}` }; if (seriesFromConnectorArray.length > 0 && axis.coll === 'xAxis' && visiblePoints.length) { let columnId; const columnAssignment = (component.connectorHandlers[0] ?.options).columnAssignment; if (columnAssignment) { const assignment = columnAssignment.find((assignment) => (assignment.seriesId === series.options.id)); if (assignment) { const data = assignment.data; if (isString(data)) { columnId = data; } else if (Array.isArray(data)) { columnId = data[data.length - 1]; } else { columnId = data.y; } } } if (!columnId) { columnId = axis.dateTime && (table.hasColumns(['x']) ? 'x' : series.options.id ?? series.name); } minCursorData.row = visiblePoints[0].index; minCursorData.column = columnId; maxCursorData.row = visiblePoints[visiblePoints.length - 1].index; maxCursorData.column = columnId; } // Emit as lasting cursors cursor.emitCursor(table, minCursorData, e, true).emitCursor(table, maxCursorData, e, true); } } }; const addExtremesEvent = () => chart.axes.map((axis) => addEvent(axis, 'afterSetExtremes', extremesEventHandler)); let addExtremesEventCallbacks = addExtremesEvent(); const resetExtremesEvent = () => { addExtremesEventCallbacks.forEach((callback) => { callback(); }); addExtremesEventCallbacks = []; }; const handleChartResetSelection = (e) => { if (e.resetSelection) { resetExtremesEvent(); cursor.emitCursor(table, { type: 'position', state: 'chart.zoomOut' + groupKey }, e); addExtremesEventCallbacks.push(...addExtremesEvent()); } }; cleanupCallbacks.push(addEvent(chart, 'selection', handleChartResetSelection)); cleanupCallbacks.push(() => { cursor.remitCursor(table.id, { type: 'position', state: 'xAxis.extremes.min' + groupKey }); cursor.remitCursor(table.id, { type: 'position', state: 'xAxis.extremes.max' + groupKey }); resetExtremesEvent(); }); } // Return cleanup return function () { // Call back the cleanup callbacks cleanupCallbacks.forEach((callback) => { callback(); }); }; }, handler: function () { if (this.type !== 'Highcharts') { return; } const component = this; const syncOptions = this.sync.syncConfig.extremes; const groupKey = syncOptions.group ? ':' + syncOptions.group : ''; const { chart, board } = component; if (chart && board && chart.zooming?.type) { const dimensions = chart.zooming.type.split('') .map((c) => c + 'Axis'); const unregisterCallbacks = []; dimensions.forEach((dimension) => { const handleUpdateExtremes = (e) => { const { cursor, event } = e; if (cursor.type === 'position') { const eventTarget = event?.target; if (eventTarget && chart) { const axes = chart[dimension]; let didZoom = false; axes.forEach((axis) => { if (eventTarget.coll === axis.coll && eventTarget !== axis && eventTarget.min !== null && eventTarget.max !== null && (axis.max !== eventTarget.max || axis.min !== eventTarget.min)) { axis.setExtremes(eventTarget.min, eventTarget.max, false, void 0, { trigger: 'dashboards-sync' }); didZoom = true; } }); if (didZoom && !chart.resetZoomButton) { chart.showResetZoom(); } chart.redraw(); } } }; const addCursorListeners = () => { const { dataCursor: cursor } = board; const connector = component.connectorHandlers?.[0]?.connector; if (connector) { const table = connector.getTable(); cursor.addListener(table.id, `${dimension}.extremes.min${groupKey}`, handleUpdateExtremes); cursor.addListener(table.id, `${dimension}.extremes.max${groupKey}`, handleUpdateExtremes); const handleChartZoomOut = () => { chart.zoomOut(); setTimeout(() => { // Workaround for zoom button not being removed const resetZoomButtons = component.element .querySelectorAll('.highcharts-reset-zoom'); resetZoomButtons.forEach((button) => { button.remove(); }); }); }; cursor.addListener(table.id, 'chart.zoomOut', handleChartZoomOut); unregisterCallbacks.push(() => { cursor.removeListener(table.id, `${dimension}.extremes.min${groupKey}`, handleUpdateExtremes); cursor.removeListener(table.id, `${dimension}.extremes.max${groupKey}`, handleUpdateExtremes); cursor.removeListener(table.id, 'chart.zoomOut' + groupKey, handleChartZoomOut); }); } }; if (board) { addCursorListeners(); } }); return function () { unregisterCallbacks.forEach((callback) => { callback(); }); }; } } }; /* * * * Default export * * */ export default { defaultOptions, syncPair };