format.ts 8.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/*
* 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.
*/

S
sushuang 已提交
20
import * as zrUtil from 'zrender/src/core/util';
S
sushuang 已提交
21
import * as numberUtil from './number';
P
pissang 已提交
22
import {TooltipRenderMode, ColorString} from './types';
P
pissang 已提交
23
import { Dictionary } from 'zrender/src/core/types';
S
sushuang 已提交
24 25

/**
26
 * Add a comma each three digit.
S
sushuang 已提交
27
 */
P
pissang 已提交
28 29
export function addCommas(x: string | number): string {
    if (isNaN(x as number)) {
S
sushuang 已提交
30 31
        return '-';
    }
P
pissang 已提交
32 33 34
    const parts = (x + '').split('.');
    return parts[0].replace(/(\d{1,3})(?=(?:\d{3})+(?!\d))/g, '$1,')
            + (parts.length > 1 ? ('.' + parts[1]) : '');
S
sushuang 已提交
35
}
S
sushuang 已提交
36

37
export function toCamelCase(str: string, upperCaseFirst?: boolean): string {
S
sushuang 已提交
38
    str = (str || '').toLowerCase().replace(/-(.)/g, function (match, group1) {
S
sushuang 已提交
39 40 41 42 43 44 45 46
        return group1.toUpperCase();
    });

    if (upperCaseFirst && str) {
        str = str.charAt(0).toUpperCase() + str.slice(1);
    }

    return str;
S
sushuang 已提交
47
}
S
sushuang 已提交
48

49
export const normalizeCssArray = zrUtil.normalizeCssArray;
S
sushuang 已提交
50

S
tweak.  
sushuang 已提交
51

52 53
const replaceReg = /([&<>"'])/g;
const replaceMap: Dictionary<string> = {
S
tweak.  
sushuang 已提交
54 55 56 57
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;',
    '"': '&quot;',
S
sushuang 已提交
58
    '\'': '&#39;'
S
tweak.  
sushuang 已提交
59 60
};

P
pissang 已提交
61
export function encodeHTML(source: string): string {
S
tweak.  
sushuang 已提交
62 63
    return source == null
        ? ''
S
sushuang 已提交
64 65
        : (source + '').replace(replaceReg, function (str, c) {
            return replaceMap[c];
S
tweak.  
sushuang 已提交
66
        });
S
sushuang 已提交
67
}
S
sushuang 已提交
68

S
susiwen8 已提交
69
export function concatTooltipHtml(html: string, value: unknown, dontEncodeHtml?: boolean): string {
S
susiwen8 已提交
70 71
    return (dontEncodeHtml ? html : `<span style="font-size:12px;color:#6e7079;">${encodeHTML(html)}</span>`)
            + (value ? '<span style="float:right;margin-left:20px;color:#464646;font-weight:900;font-size:14px";>' : '')
S
susiwen8 已提交
72
            + encodeHTML(value as string)
S
susiwen8 已提交
73
            + (value ? '</span>' : '');
S
susiwen8 已提交
74 75
}

76
const TPL_VAR_ALIAS = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
S
sushuang 已提交
77

78
const wrapVar = function (varName: string, seriesIdx?: number): string {
S
sushuang 已提交
79 80 81
    return '{' + varName + (seriesIdx == null ? '' : seriesIdx) + '}';
};

P
pissang 已提交
82
export interface TplFormatterParam extends Dictionary<any> {
83 84 85
    // Param name list for mapping `a`, `b`, `c`, `d`, `e`
    $vars: string[];
}
S
sushuang 已提交
86 87 88 89
/**
 * Template formatter
 * @param {Array.<Object>|Object} paramsList
 */
90 91 92 93 94
export function formatTpl(
    tpl: string,
    paramsList: TplFormatterParam | TplFormatterParam[],
    encode?: boolean
): string {
S
sushuang 已提交
95 96 97
    if (!zrUtil.isArray(paramsList)) {
        paramsList = [paramsList];
    }
98
    const seriesLen = paramsList.length;
S
sushuang 已提交
99 100 101 102
    if (!seriesLen) {
        return '';
    }

103
    const $vars = paramsList[0].$vars || [];
104
    for (let i = 0; i < $vars.length; i++) {
105
        const alias = TPL_VAR_ALIAS[i];
S
sushuang 已提交
106
        tpl = tpl.replace(wrapVar(alias), wrapVar(alias, 0));
S
sushuang 已提交
107
    }
108 109
    for (let seriesIdx = 0; seriesIdx < seriesLen; seriesIdx++) {
        for (let k = 0; k < $vars.length; k++) {
110
            const val = paramsList[seriesIdx][$vars[k]];
D
dengxiaohong01 已提交
111
            tpl = tpl.replace(
S
sushuang 已提交
112 113
                wrapVar(TPL_VAR_ALIAS[k], seriesIdx),
                encode ? encodeHTML(val) : val
D
dengxiaohong01 已提交
114
            );
D
deqingli 已提交
115
        }
S
sushuang 已提交
116 117 118
    }

    return tpl;
S
sushuang 已提交
119
}
S
sushuang 已提交
120 121 122 123

/**
 * simple Template formatter
 */
P
pissang 已提交
124
export function formatTplSimple(tpl: string, param: Dictionary<any>, encode?: boolean) {
S
sushuang 已提交
125 126 127 128 129 130 131
    zrUtil.each(param, function (value, key) {
        tpl = tpl.replace(
            '{' + key + '}',
            encode ? encodeHTML(value) : value
        );
    });
    return tpl;
S
sushuang 已提交
132
}
S
sushuang 已提交
133

134 135 136 137
interface RichTextTooltipMarker {
    renderMode: TooltipRenderMode;
    content: string;
    style: {
P
pissang 已提交
138
        color: ColorString
139 140 141 142 143
        [key: string]: any
    };
}
export type TooltipMarker = string | RichTextTooltipMarker;
interface GetTooltipMarkerOpt {
P
pissang 已提交
144
    color?: ColorString;
145 146 147 148 149 150 151 152
    extraCssText?: string;
    // By default: 'item'
    type?: 'item' | 'subItem';
    renderMode?: TooltipRenderMode;
    // id name for marker. If only one marker is in a rich text, this can be omitted.
    // By default: 'X'
    markerId?: string;
}
P
pissang 已提交
153 154
// Only support color string
export function getTooltipMarker(color: ColorString, extraCssText?: string): TooltipMarker;
155
export function getTooltipMarker(opt: GetTooltipMarkerOpt): TooltipMarker;
P
pissang 已提交
156
export function getTooltipMarker(inOpt: ColorString | GetTooltipMarkerOpt, extraCssText?: string): TooltipMarker {
157
    const opt = zrUtil.isString(inOpt) ? {
P
pissang 已提交
158 159 160
        color: inOpt,
        extraCssText: extraCssText
    } : (inOpt || {}) as GetTooltipMarkerOpt;
161 162
    const color = opt.color;
    const type = opt.type;
1
100pah 已提交
163
    extraCssText = opt.extraCssText;
164 165
    const renderMode = opt.renderMode || 'html';
    const markerId = opt.markerId || 'X';
S
tweak  
sushuang 已提交
166 167 168 169 170

    if (!color) {
        return '';
    }

171
    if (renderMode === 'html') {
172
        return type === 'subItem'
S
tweak  
sushuang 已提交
173 174
        ? '<span style="display:inline-block;vertical-align:middle;margin-right:8px;margin-left:3px;'
            + 'border-radius:4px;width:4px;height:4px;background-color:'
P
pissang 已提交
175
            // Only support string
S
sushuang 已提交
176
            + encodeHTML(color) + ';' + (extraCssText || '') + '"></span>'
S
susiwen8 已提交
177
        : '<span style="display:inline-block;margin-right:4px;'
S
tweak  
sushuang 已提交
178 179
            + 'border-radius:10px;width:10px;height:10px;background-color:'
            + encodeHTML(color) + ';' + (extraCssText || '') + '"></span>';
180
    }
181 182 183 184 185 186 187 188 189 190
    else {
        // Space for rich element marker
        return {
            renderMode: renderMode,
            content: '{marker' + markerId + '|}  ',
            style: {
                color: color
            }
        };
    }
S
sushuang 已提交
191
}
S
sushuang 已提交
192

P
pissang 已提交
193
function pad(str: string, len: number): string {
S
sushuang 已提交
194 195 196 197
    str += '';
    return '0000'.substr(0, len - str.length) + str;
}

S
sushuang 已提交
198 199 200 201 202 203 204 205 206 207

/**
 * 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
 */
1
100pah 已提交
208
export function formatTime(tpl: string, value: number | string | Date, isUTC?: boolean) {
S
sushuang 已提交
209 210 211 212 213 214 215 216 217
    if (tpl === 'week'
        || tpl === 'month'
        || tpl === 'quarter'
        || tpl === 'half-year'
        || tpl === 'year'
    ) {
        tpl = 'MM-dd\nyyyy';
    }

218 219 220 221 222 223 224 225 226
    const date = numberUtil.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']();
S
sushuang 已提交
227

S
sushuang 已提交
228
    tpl = tpl.replace('MM', pad(M, 2))
S
sushuang 已提交
229 230
        .replace('M', M)
        .replace('yyyy', y)
P
pissang 已提交
231
        .replace('yy', y % 100 + '')
S
sushuang 已提交
232
        .replace('dd', pad(d, 2))
S
sushuang 已提交
233
        .replace('d', d)
S
sushuang 已提交
234
        .replace('hh', pad(h, 2))
S
sushuang 已提交
235
        .replace('h', h)
S
sushuang 已提交
236
        .replace('mm', pad(m, 2))
S
sushuang 已提交
237
        .replace('m', m)
S
sushuang 已提交
238 239 240
        .replace('ss', pad(s, 2))
        .replace('s', s)
        .replace('SSS', pad(S, 3));
S
sushuang 已提交
241 242

    return tpl;
S
sushuang 已提交
243
}
S
sushuang 已提交
244 245 246 247 248 249

/**
 * Capital first
 * @param {string} str
 * @return {string}
 */
P
pissang 已提交
250
export function capitalFirst(str: string): string {
S
sushuang 已提交
251
    return str ? str.charAt(0).toUpperCase() + str.substr(1) : str;
P
pissang 已提交
252 253 254
}


255
export {truncateText} from 'zrender/src/graphic/helper/parseText';
S
susiwen8 已提交
256 257 258

/**
 * open new tab
259 260
 * @param link url
 * @param target blank or self
S
susiwen8 已提交
261
 */
262
export function windowOpen(link: string, target: string): void {
S
susiwen8 已提交
263
    if (target === '_blank' || target === 'blank') {
264
        const blank = window.open();
S
susiwen8 已提交
265
        blank.opener = null;
266
        blank.location.href = link;
S
susiwen8 已提交
267 268 269 270 271
    }
    else {
        window.open(link, target);
    }
}
272 273 274


export {getTextRect} from '../legacy/getTextRect';