/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ import SeriesModel from '../../model/Series'; import { trim, isArray, each, reduce } from 'zrender/src/core/util'; import { DimensionName, DimensionType, ColorString } from '../../util/types'; import { retrieveVisualColorForTooltipMarker, TooltipMarkupBlockFragment, createTooltipMarkup, TooltipMarkupSection } from './tooltipMarkup'; import { retrieveRawValue } from '../../data/helper/dataProvider'; import { isNameSpecified } from '../../util/model'; export function defaultSeriesFormatTooltip(opt: { series: SeriesModel; dataIndex: number; // `multipleSeries` means multiple series displayed in one tooltip, // and this method only return the part of one series. multipleSeries: boolean; }): TooltipMarkupSection { const series = opt.series; const dataIndex = opt.dataIndex; const multipleSeries = opt.multipleSeries; const data = series.getData(); const tooltipDims = data.mapDimensionsAll('defaultedTooltip'); const tooltipDimLen = tooltipDims.length; const value = series.getRawValue(dataIndex) as any; const isValueArr = isArray(value); const markerColor = retrieveVisualColorForTooltipMarker(series, dataIndex); // Complicated rule for pretty tooltip. let inlineValue; let inlineValueType: DimensionType | DimensionType[]; let subBlocks: TooltipMarkupBlockFragment[]; let sortParam: unknown; if (tooltipDimLen > 1 || (isValueArr && !tooltipDimLen)) { const formatArrResult = formatTooltipArrayValue(value, series, dataIndex, tooltipDims, markerColor); inlineValue = formatArrResult.inlineValues; inlineValueType = formatArrResult.inlineValueTypes; subBlocks = formatArrResult.blocks; // Only support tooltip sort by the first inline value. It's enough in most cases. sortParam = formatArrResult.inlineValues[0]; } else if (tooltipDimLen) { const dimInfo = data.getDimensionInfo(tooltipDims[0]); sortParam = inlineValue = retrieveRawValue(data, dataIndex, tooltipDims[0]); inlineValueType = dimInfo.type; } else { sortParam = inlineValue = isValueArr ? value[0] : value; } // Do not show generated series name. It might not be readable. const seriesNameSpecified = isNameSpecified(series); const seriesName = seriesNameSpecified && series.name || ''; const itemName = data.getName(dataIndex); const inlineName = multipleSeries ? seriesName : itemName; return createTooltipMarkup('section', { header: seriesName, // When series name is not specified, do not show a header line with only '-'. // This case always happens in tooltip.trigger: 'item'. noHeader: multipleSeries || !seriesNameSpecified, sortParam: sortParam, blocks: [ createTooltipMarkup('nameValue', { markerType: 'item', markerColor: markerColor, // Do not mix display seriesName and itemName in one tooltip, // which might confuses users. name: inlineName, // name dimension might be auto assigned, where the name might // be not readable. So we check trim here. noName: !trim(inlineName), value: inlineValue, valueType: inlineValueType }) ].concat(subBlocks || [] as any) }); } function formatTooltipArrayValue( value: unknown[], series: SeriesModel, dataIndex: number, tooltipDims: DimensionName[], colorStr: ColorString ): { inlineValues: unknown[]; inlineValueTypes: DimensionType[]; blocks: TooltipMarkupBlockFragment[]; } { // check: category-no-encode-has-axis-data in dataset.html const data = series.getData(); const isValueMultipleLine = reduce(value, function (isValueMultipleLine, val, idx) { const dimItem = data.getDimensionInfo(idx); return isValueMultipleLine = isValueMultipleLine || (dimItem && dimItem.tooltip !== false && dimItem.displayName != null); }, false); const inlineValues: unknown[] = []; const inlineValueTypes: DimensionType[] = []; const blocks: TooltipMarkupBlockFragment[] = []; tooltipDims.length ? each(tooltipDims, function (dim) { setEachItem(retrieveRawValue(data, dataIndex, dim), dim); }) // By default, all dims is used on tooltip. : each(value, setEachItem); function setEachItem(val: unknown, dim: DimensionName | number): void { const dimInfo = data.getDimensionInfo(dim); // If `dimInfo.tooltip` is not set, show tooltip. if (!dimInfo || dimInfo.otherDims.tooltip === false) { return; } if (isValueMultipleLine) { blocks.push(createTooltipMarkup('nameValue', { markerType: 'subItem', markerColor: colorStr, name: dimInfo.displayName, value: val, valueType: dimInfo.type })); } else { inlineValues.push(val); inlineValueTypes.push(dimInfo.type); } } return { inlineValues, inlineValueTypes, blocks }; }