| /* |
| * 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 { parseDate, isNumeric, numericToNumber } from './number'; |
| import { TooltipRenderMode, ColorString, ZRColor, DimensionType } from './types'; |
| import { Dictionary } from 'zrender/src/core/types'; |
| import { GradientObject } from 'zrender/src/graphic/Gradient'; |
| import { format as timeFormat, pad } from './time'; |
| import { deprecateReplaceLog } from './log'; |
| |
| /** |
| * Add a comma each three digit. |
| */ |
| export function addCommas(x: string | number): string { |
| if (!isNumeric(x)) { |
| return zrUtil.isString(x) ? x : '-'; |
| } |
| const parts = (x + '').split('.'); |
| return parts[0].replace(/(\d{1,3})(?=(?:\d{3})+(?!\d))/g, '$1,') |
| + (parts.length > 1 ? ('.' + parts[1]) : ''); |
| } |
| |
| export function toCamelCase(str: string, upperCaseFirst?: boolean): string { |
| str = (str || '').toLowerCase().replace(/-(.)/g, function (match, group1) { |
| return group1.toUpperCase(); |
| }); |
| |
| if (upperCaseFirst && str) { |
| str = str.charAt(0).toUpperCase() + str.slice(1); |
| } |
| |
| return str; |
| } |
| |
| export const normalizeCssArray = zrUtil.normalizeCssArray; |
| |
| |
| const replaceReg = /([&<>"'])/g; |
| const replaceMap: Dictionary<string> = { |
| '&': '&', |
| '<': '<', |
| '>': '>', |
| '"': '"', |
| '\'': ''' |
| }; |
| |
| export function encodeHTML(source: string): string { |
| return source == null |
| ? '' |
| : (source + '').replace(replaceReg, function (str, c) { |
| return replaceMap[c]; |
| }); |
| } |
| |
| |
| /** |
| * Make value user readable for tooltip and label. |
| * "User readable": |
| * Try to not print programmer-specific text like NaN, Infinity, null, undefined. |
| * Avoid to display an empty string, which users can not recognize there is |
| * a value and it might look like a bug. |
| */ |
| export function makeValueReadable( |
| value: unknown, |
| valueType: DimensionType, |
| useUTC: boolean |
| ): string { |
| const USER_READABLE_DEFUALT_TIME_PATTERN = 'yyyy-MM-dd hh:mm:ss'; |
| |
| function stringToUserReadable(str: string): string { |
| return (str && zrUtil.trim(str)) ? str : '-'; |
| } |
| function isNumberUserReadable(num: number): boolean { |
| return !!(num != null && !isNaN(num) && isFinite(num)); |
| } |
| |
| const isTypeTime = valueType === 'time'; |
| const isValueDate = value instanceof Date; |
| if (isTypeTime || isValueDate) { |
| const date = isTypeTime ? parseDate(value) : value; |
| if (!isNaN(+date)) { |
| return timeFormat(date, USER_READABLE_DEFUALT_TIME_PATTERN, useUTC); |
| } |
| else if (isValueDate) { |
| return '-'; |
| } |
| // In other cases, continue to try to display the value in the following code. |
| } |
| |
| if (valueType === 'ordinal') { |
| return zrUtil.isStringSafe(value) |
| ? stringToUserReadable(value) |
| : zrUtil.isNumber(value) |
| ? (isNumberUserReadable(value) ? value + '' : '-') |
| : '-'; |
| } |
| // By default. |
| const numericResult = numericToNumber(value); |
| return isNumberUserReadable(numericResult) |
| ? addCommas(numericResult) |
| : zrUtil.isStringSafe(value) |
| ? stringToUserReadable(value) |
| : '-'; |
| } |
| |
| |
| const TPL_VAR_ALIAS = ['a', 'b', 'c', 'd', 'e', 'f', 'g']; |
| |
| const wrapVar = function (varName: string, seriesIdx?: number): string { |
| return '{' + varName + (seriesIdx == null ? '' : seriesIdx) + '}'; |
| }; |
| |
| export interface TplFormatterParam extends Dictionary<any> { |
| // Param name list for mapping `a`, `b`, `c`, `d`, `e` |
| $vars: string[]; |
| } |
| /** |
| * Template formatter |
| * @param {Array.<Object>|Object} paramsList |
| */ |
| export function formatTpl( |
| tpl: string, |
| paramsList: TplFormatterParam | TplFormatterParam[], |
| encode?: boolean |
| ): string { |
| if (!zrUtil.isArray(paramsList)) { |
| paramsList = [paramsList]; |
| } |
| const seriesLen = paramsList.length; |
| if (!seriesLen) { |
| return ''; |
| } |
| |
| const $vars = paramsList[0].$vars || []; |
| for (let i = 0; i < $vars.length; i++) { |
| const alias = TPL_VAR_ALIAS[i]; |
| tpl = tpl.replace(wrapVar(alias), wrapVar(alias, 0)); |
| } |
| for (let seriesIdx = 0; seriesIdx < seriesLen; seriesIdx++) { |
| for (let k = 0; k < $vars.length; k++) { |
| const val = paramsList[seriesIdx][$vars[k]]; |
| tpl = tpl.replace( |
| wrapVar(TPL_VAR_ALIAS[k], seriesIdx), |
| encode ? encodeHTML(val) : val |
| ); |
| } |
| } |
| |
| return tpl; |
| } |
| |
| /** |
| * simple Template formatter |
| */ |
| export function formatTplSimple(tpl: string, param: Dictionary<any>, encode?: boolean) { |
| zrUtil.each(param, function (value, key) { |
| tpl = tpl.replace( |
| '{' + key + '}', |
| encode ? encodeHTML(value) : value |
| ); |
| }); |
| return tpl; |
| } |
| |
| interface RichTextTooltipMarker { |
| renderMode: TooltipRenderMode; |
| content: string; |
| style: Dictionary<unknown>; |
| } |
| export type TooltipMarker = string | RichTextTooltipMarker; |
| export type TooltipMarkerType = 'item' | 'subItem'; |
| interface GetTooltipMarkerOpt { |
| color?: ColorString; |
| extraCssText?: string; |
| // By default: 'item' |
| type?: TooltipMarkerType; |
| renderMode?: TooltipRenderMode; |
| // id name for marker. If only one marker is in a rich text, this can be omitted. |
| // By default: 'markerX' |
| markerId?: string; |
| } |
| // Only support color string |
| export function getTooltipMarker(color: ColorString, extraCssText?: string): TooltipMarker; |
| export function getTooltipMarker(opt: GetTooltipMarkerOpt): TooltipMarker; |
| export function getTooltipMarker(inOpt: ColorString | GetTooltipMarkerOpt, extraCssText?: string): TooltipMarker { |
| const opt = zrUtil.isString(inOpt) ? { |
| color: inOpt, |
| extraCssText: extraCssText |
| } : (inOpt || {}) as GetTooltipMarkerOpt; |
| const color = opt.color; |
| const type = opt.type; |
| extraCssText = opt.extraCssText; |
| const renderMode = opt.renderMode || 'html'; |
| |
| if (!color) { |
| return ''; |
| } |
| |
| if (renderMode === 'html') { |
| return type === 'subItem' |
| ? '<span style="display:inline-block;vertical-align:middle;margin-right:8px;margin-left:3px;' |
| + 'border-radius:4px;width:4px;height:4px;background-color:' |
| // Only support string |
| + encodeHTML(color) + ';' + (extraCssText || '') + '"></span>' |
| : '<span style="display:inline-block;margin-right:4px;' |
| + 'border-radius:10px;width:10px;height:10px;background-color:' |
| + encodeHTML(color) + ';' + (extraCssText || '') + '"></span>'; |
| } |
| else { |
| // Should better not to auto generate style name by auto-increment number here. |
| // Because this util is usually called in tooltip formatter, which is probably |
| // called repeatly when mouse move and the auto-increment number increases fast. |
| // Users can make their own style name by theirselves, make it unique and readable. |
| const markerId = opt.markerId || 'markerX'; |
| return { |
| renderMode: renderMode, |
| content: '{' + markerId + '|} ', |
| style: type === 'subItem' |
| ? { |
| width: 4, |
| height: 4, |
| borderRadius: 2, |
| backgroundColor: color |
| } |
| : { |
| width: 10, |
| height: 10, |
| borderRadius: 5, |
| backgroundColor: color |
| } |
| }; |
| } |
| } |
| |
| |
| /** |
| * @deprecated Use `time/format` instead. |
| * ISO Date format |
| * @param {string} tpl |
| * @param {number} value |
| * @param {boolean} [isUTC=false] Default in local time. |
| * see `module:echarts/scale/Time` |
| * and `module:echarts/util/number#parseDate`. |
| * @inner |
| */ |
| export function formatTime(tpl: string, value: unknown, isUTC: boolean) { |
| if (__DEV__) { |
| deprecateReplaceLog('echarts.format.formatTime', 'echarts.time.format'); |
| } |
| |
| if (tpl === 'week' |
| || tpl === 'month' |
| || tpl === 'quarter' |
| || tpl === 'half-year' |
| || tpl === 'year' |
| ) { |
| tpl = 'MM-dd\nyyyy'; |
| } |
| |
| const date = parseDate(value); |
| const utc = isUTC ? 'UTC' : ''; |
| const y = (date as any)['get' + utc + 'FullYear'](); |
| const M = (date as any)['get' + utc + 'Month']() + 1; |
| const d = (date as any)['get' + utc + 'Date'](); |
| const h = (date as any)['get' + utc + 'Hours'](); |
| const m = (date as any)['get' + utc + 'Minutes'](); |
| const s = (date as any)['get' + utc + 'Seconds'](); |
| const S = (date as any)['get' + utc + 'Milliseconds'](); |
| |
| tpl = tpl.replace('MM', pad(M, 2)) |
| .replace('M', M) |
| .replace('yyyy', y) |
| .replace('yy', y % 100 + '') |
| .replace('dd', pad(d, 2)) |
| .replace('d', d) |
| .replace('hh', pad(h, 2)) |
| .replace('h', h) |
| .replace('mm', pad(m, 2)) |
| .replace('m', m) |
| .replace('ss', pad(s, 2)) |
| .replace('s', s) |
| .replace('SSS', pad(S, 3)); |
| |
| return tpl; |
| } |
| |
| /** |
| * Capital first |
| * @param {string} str |
| * @return {string} |
| */ |
| export function capitalFirst(str: string): string { |
| return str ? str.charAt(0).toUpperCase() + str.substr(1) : str; |
| } |
| |
| /** |
| * @return Never be null/undefined. |
| */ |
| export function convertToColorString(color: ZRColor, defaultColor?: ColorString): ColorString { |
| defaultColor = defaultColor || 'transparent'; |
| return zrUtil.isString(color) |
| ? color |
| : zrUtil.isObject(color) |
| ? ( |
| (color as GradientObject).colorStops |
| && ((color as GradientObject).colorStops[0] || {}).color |
| || defaultColor |
| ) |
| : defaultColor; |
| } |
| |
| export {truncateText} from 'zrender/src/graphic/helper/parseText'; |
| |
| /** |
| * open new tab |
| * @param link url |
| * @param target blank or self |
| */ |
| export function windowOpen(link: string, target: string): void { |
| /* global window */ |
| if (target === '_blank' || target === 'blank') { |
| const blank = window.open(); |
| blank.opener = null; |
| blank.location.href = link; |
| } |
| else { |
| window.open(link, target); |
| } |
| } |
| |
| |
| export {getTextRect} from '../legacy/getTextRect'; |