| /* |
| * 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 * as zrUtil from 'zrender/src/core/util'; |
| import {retrieveRawValue} from '../../data/helper/dataProvider'; |
| import {formatTpl} from '../../util/format'; |
| import { |
| DataHost, |
| DisplayState, |
| CallbackDataParams, |
| ColorString, |
| ZRColor, |
| OptionDataValue, |
| SeriesDataType, |
| ComponentMainType, |
| ComponentSubType, |
| DimensionLoose, |
| InterpolatableValue, |
| } from '../../util/types'; |
| import GlobalModel from '../Global'; |
| import { TooltipMarkupBlockFragment } from '../../component/tooltip/tooltipMarkup'; |
| import { error, makePrintable } from '../../util/log'; |
| |
| const DIMENSION_LABEL_REG = /\{@(.+?)\}/g; |
| |
| |
| export interface DataFormatMixin extends DataHost { |
| ecModel: GlobalModel; |
| mainType: ComponentMainType; |
| subType: ComponentSubType; |
| componentIndex: number; |
| id: string; |
| name: string; |
| animatedValue: OptionDataValue[]; |
| } |
| |
| export class DataFormatMixin { |
| |
| /** |
| * Get params for formatter |
| */ |
| getDataParams( |
| dataIndex: number, |
| dataType?: SeriesDataType |
| ): CallbackDataParams { |
| |
| const data = this.getData(dataType); |
| const rawValue = this.getRawValue(dataIndex, dataType); |
| const rawDataIndex = data.getRawIndex(dataIndex); |
| const name = data.getName(dataIndex); |
| const itemOpt = data.getRawDataItem(dataIndex); |
| const style = data.getItemVisual(dataIndex, 'style'); |
| const color = style && style[data.getItemVisual(dataIndex, 'drawType') || 'fill'] as ZRColor; |
| const borderColor = style && style.stroke as ColorString; |
| const mainType = this.mainType; |
| const isSeries = mainType === 'series'; |
| const userOutput = data.userOutput && data.userOutput.get(); |
| |
| return { |
| componentType: mainType, |
| componentSubType: this.subType, |
| componentIndex: this.componentIndex, |
| seriesType: isSeries ? this.subType : null, |
| seriesIndex: (this as any).seriesIndex, |
| seriesId: isSeries ? this.id : null, |
| seriesName: isSeries ? this.name : null, |
| name: name, |
| dataIndex: rawDataIndex, |
| data: itemOpt, |
| dataType: dataType, |
| value: rawValue, |
| color: color, |
| borderColor: borderColor, |
| dimensionNames: userOutput ? userOutput.fullDimensions : null, |
| encode: userOutput ? userOutput.encode : null, |
| |
| // Param name list for mapping `a`, `b`, `c`, `d`, `e` |
| $vars: ['seriesName', 'name', 'value'] |
| }; |
| } |
| |
| /** |
| * Format label |
| * @param dataIndex |
| * @param status 'normal' by default |
| * @param dataType |
| * @param labelDimIndex Only used in some chart that |
| * use formatter in different dimensions, like radar. |
| * @param formatter Formatter given outside. |
| * @return return null/undefined if no formatter |
| */ |
| getFormattedLabel( |
| dataIndex: number, |
| status?: DisplayState, |
| dataType?: SeriesDataType, |
| labelDimIndex?: number, |
| formatter?: string | ((params: object) => string), |
| extendParams?: { |
| interpolatedValue: InterpolatableValue |
| } |
| ): string { |
| status = status || 'normal'; |
| const data = this.getData(dataType); |
| |
| const params = this.getDataParams(dataIndex, dataType); |
| |
| if (extendParams) { |
| params.value = extendParams.interpolatedValue; |
| } |
| |
| if (labelDimIndex != null && zrUtil.isArray(params.value)) { |
| params.value = params.value[labelDimIndex]; |
| } |
| |
| if (!formatter) { |
| const itemModel = data.getItemModel(dataIndex); |
| // @ts-ignore |
| formatter = itemModel.get(status === 'normal' |
| ? ['label', 'formatter'] |
| : [status, 'label', 'formatter'] |
| ); |
| } |
| |
| if (zrUtil.isFunction(formatter)) { |
| params.status = status; |
| params.dimensionIndex = labelDimIndex; |
| return formatter(params); |
| } |
| else if (zrUtil.isString(formatter)) { |
| const str = formatTpl(formatter, params); |
| |
| // Support 'aaa{@[3]}bbb{@product}ccc'. |
| // Do not support '}' in dim name util have to. |
| return str.replace(DIMENSION_LABEL_REG, function (origin, dimStr: string) { |
| const len = dimStr.length; |
| |
| let dimLoose: DimensionLoose = dimStr; |
| if (dimLoose.charAt(0) === '[' && dimLoose.charAt(len - 1) === ']') { |
| dimLoose = +dimLoose.slice(1, len - 1); // Also support: '[]' => 0 |
| if (__DEV__) { |
| if (isNaN(dimLoose)) { |
| error(`Invalide label formatter: @${dimStr}, only support @[0], @[1], @[2], ...`); |
| } |
| } |
| } |
| |
| let val = retrieveRawValue(data, dataIndex, dimLoose) as OptionDataValue; |
| |
| if (extendParams && zrUtil.isArray(extendParams.interpolatedValue)) { |
| const dimIndex = data.getDimensionIndex(dimLoose); |
| if (dimIndex >= 0) { |
| val = extendParams.interpolatedValue[dimIndex]; |
| } |
| } |
| |
| return val != null ? val + '' : ''; |
| }); |
| } |
| } |
| |
| /** |
| * Get raw value in option |
| */ |
| getRawValue( |
| idx: number, |
| dataType?: SeriesDataType |
| ): unknown { |
| return retrieveRawValue(this.getData(dataType), idx); |
| } |
| |
| /** |
| * Should be implemented. |
| * @param {number} dataIndex |
| * @param {boolean} [multipleSeries=false] |
| * @param {string} [dataType] |
| */ |
| formatTooltip( |
| dataIndex: number, |
| multipleSeries?: boolean, |
| dataType?: string |
| ): TooltipFormatResult { |
| // Empty function |
| return; |
| } |
| }; |
| |
| type TooltipFormatResult = |
| // If `string`, means `TooltipFormatResultLegacyObject['html']` |
| string |
| // | TooltipFormatResultLegacyObject |
| | TooltipMarkupBlockFragment; |
| |
| // PENDING: previously we accept this type when calling `formatTooltip`, |
| // but guess little chance has been used outside. Do we need to backward |
| // compat it? |
| // type TooltipFormatResultLegacyObject = { |
| // // `html` means the markup language text, either in 'html' or 'richText'. |
| // // The name `html` is not appropriate becuase in 'richText' it is not a HTML |
| // // string. But still support it for backward compat. |
| // html: string; |
| // markers: Dictionary<ColorString>; |
| // }; |
| |
| /** |
| * For backward compat, normalize the return from `formatTooltip`. |
| */ |
| export function normalizeTooltipFormatResult(result: TooltipFormatResult): { |
| // If `markupFragment` exists, `markupText` should be ignored. |
| frag: TooltipMarkupBlockFragment; |
| // Can be `null`/`undefined`, means no tooltip. |
| text: string; |
| // Merged with `markersExisting`. |
| // markers: Dictionary<ColorString>; |
| } { |
| let markupText; |
| // let markers: Dictionary<ColorString>; |
| let markupFragment: TooltipMarkupBlockFragment; |
| if (zrUtil.isObject(result)) { |
| if ((result as TooltipMarkupBlockFragment).type) { |
| markupFragment = result as TooltipMarkupBlockFragment; |
| } |
| else { |
| if (__DEV__) { |
| console.warn('The return type of `formatTooltip` is not supported: ' + makePrintable(result)); |
| } |
| } |
| // else { |
| // markupText = (result as TooltipFormatResultLegacyObject).html; |
| // markers = (result as TooltipFormatResultLegacyObject).markers; |
| // if (markersExisting) { |
| // markers = zrUtil.merge(markersExisting, markers); |
| // } |
| // } |
| } |
| else { |
| markupText = result; |
| } |
| |
| return { |
| text: markupText, |
| // markers: markers || markersExisting, |
| frag: markupFragment |
| }; |
| } |