UNPKG

@syncfusion/ej2-charts

Version:

Feature-rich chart control with built-in support for over 25 chart types, technical indictors, trendline, zooming, tooltip, selection, crosshair and trackball.

392 lines (391 loc) 16.8 kB
var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0) t[p[i]] = s[p[i]]; return t; }; import { PathOption, drawPath, getIdElement, Rect, withInBounds } from '../utils/helper'; import { Browser, extend, isNullOrUndefined, remove, createElement } from '@syncfusion/ej2-base'; import { Tooltip } from '@syncfusion/ej2-svg-base'; /** * Sparkline Tooltip Module */ var SparklineTooltip = /** @class */ (function () { function SparklineTooltip(sparkline) { this.sparkline = sparkline; this.addEventListener(); } /** * @hidden * @returns {void} */ SparklineTooltip.prototype.addEventListener = function () { if (this.sparkline.isDestroyed) { return; } // this.sparkline.on('mouseleave', this.mouseLeaveHandler, this); this.sparkline.on(Browser.isPointer ? 'pointerleave' : 'mouseleave', this.mouseLeaveHandler, this); this.sparkline.on(Browser.touchMoveEvent, this.mouseMoveHandler, this); this.sparkline.on(Browser.touchEndEvent, this.mouseUpHandler, this); }; SparklineTooltip.prototype.mouseLeaveHandler = function () { this.removeTooltipElements(); }; SparklineTooltip.prototype.mouseUpHandler = function (e) { if (!this.sparkline.isTouch) { return; } this.processTooltip(e); this.fadeOut(); }; SparklineTooltip.prototype.fadeOut = function () { clearTimeout(this.clearTooltip); this.clearTooltip = +setTimeout(this.removeTooltipElements.bind(this), 5000); }; /** * To remove tooltip and tracker elements. * * @private * @returns {void} */ SparklineTooltip.prototype.removeTooltipElements = function () { this.removeTooltip(); this.removeTracker(); }; SparklineTooltip.prototype.mouseMoveHandler = function (e) { this.processTooltip(e); }; SparklineTooltip.prototype.processTooltip = function (e) { var pointIndex; var spark = this.sparkline; var visiblePoints = spark.sparklineRenderer.visiblePoints; var mouseX = spark.mouseX; var mouseY = spark.mouseY; if (spark.type !== 'Pie') { var locations = extend([], [], visiblePoints); var trackerPositions = locations.map(function (point) { return point.location.x; }); var temp = Infinity; for (var i = 0, diff = void 0, len = trackerPositions.length; i < len; i++) { diff = Math.abs(mouseX - trackerPositions[i]); if (temp > diff) { temp = diff; pointIndex = i; } } } else { var target = e.target.id; pointIndex = parseInt(target.split('_pie_')[1], 10); } if (isNaN(pointIndex) || !withInBounds(mouseX, mouseY, new Rect(0, 0, spark.availableSize.width, spark.availableSize.height))) { this.removeTracker(); this.removeTooltip(); return; } if (this.pointIndex === pointIndex) { return; } this.pointIndex = pointIndex; this.renderTrackerLine(visiblePoints[pointIndex]); this.renderTooltip(visiblePoints[pointIndex]); }; /** * To render tracker line. * * @param {SparkValues} points - The data points for rendering the tracker line. * @returns {void} */ SparklineTooltip.prototype.renderTrackerLine = function (points) { var spark = this.sparkline; var tracker = spark.tooltipSettings.trackLineSettings; var color = spark.sparkTheme.trackerLineColor ? spark.sparkTheme.trackerLineColor : tracker.color; if (!tracker.visible || spark.type === 'Pie') { return; } var group = getIdElement(spark.element.id + '_sparkline_tracker_g'); if (isNullOrUndefined(group)) { group = spark.renderer.createGroup({ id: spark.element.id + '_sparkline_tracker_g' }); spark.svgObject.appendChild(group); } var pathEle = getIdElement(spark.element.id + '_sparkline_tracker'); var d = 'M ' + points.location.x + ' ' + spark.padding.top + ' L ' + points.location.x + ' ' + (spark.availableSize.height - spark.padding.bottom); if (isNullOrUndefined(pathEle)) { var pathOption = new PathOption(spark.element.id + '_sparkline_tracker', color, tracker.width, color, 1); pathOption.d = d; drawPath(spark, pathOption, group); } else { pathEle.setAttribute('d', d); pathEle.setAttribute('stroke-width', tracker.width.toString()); pathEle.setAttribute('stroke', color); } }; /** * To render tooltip. * * @param {SparkValues} points - The data points for rendering the tooltip. * @returns {void} */ SparklineTooltip.prototype.renderTooltip = function (points) { var _this = this; var spark = this.sparkline; var tooltip = spark.tooltipSettings; if (!tooltip.visible) { return; } var div = getIdElement(spark.element.id + '_sparkline_tooltip_div'); if (isNullOrUndefined(div)) { div = createElement('div', { id: spark.element.id + '_sparkline_tooltip_div', styles: 'pointer-events: none; position: absolute;z-index:1;' }); getIdElement(spark.element.id + '_Secondary_Element').appendChild(div); } var x = points.xVal.toString(); if (spark.valueType === 'Category') { x = spark.dataSource[points.xVal][spark.xName]; } else if (spark.valueType === 'DateTime') { x = new Date(points.xVal).toDateString(); } var text = this.getFormat(spark.tooltipSettings.format, spark, x, this.formatValue(points.yVal, spark).toString(), points); var location = { x: points.location.x, y: points.location.y }; location = spark.type === 'Pie' ? { x: points.location.x, y: points.location.y } : location; var textColor = tooltip.textStyle.color || spark.sparkTheme.tooltipFontColor; var backgroundColor = tooltip.fill === '' ? spark.sparkTheme.tooltipFill : tooltip.fill; var tooltipEvent = { name: 'tooltipInitialize', cancel: false, text: text, textStyle: { size: tooltip.textStyle.size, opacity: spark.sparkTheme.tooltipTextOpacity || tooltip.textStyle.opacity, fontWeight: tooltip.textStyle.fontWeight || spark.sparkTheme.tooltipFontWeight, fontStyle: tooltip.textStyle.fontStyle, fontFamily: tooltip.textStyle.fontFamily || spark.sparkTheme.tooltipFontFamily, color: textColor } }; spark.trigger('tooltipInitialize', tooltipEvent, function () { _this.addTooltip(tooltipEvent, spark, backgroundColor, tooltip, location, div); }); }; SparklineTooltip.prototype.addTooltip = function (tooltipEvent, spark, backgroundColor, tooltip, location, div, eventArgs) { var cancel; var arg; var tootipArgs; if (!isNullOrUndefined(tooltipEvent)) { var c = tooltipEvent.cancel, otherArgs = __rest(tooltipEvent, ["cancel"]); cancel = c; tootipArgs = tooltipEvent; } else { cancel = eventArgs.cancel; arg = eventArgs; tootipArgs = eventArgs; } if (tooltipEvent.cancel) { return; } var element = new Tooltip({ content: tootipArgs.text, border: tooltip.border, template: tooltip.template, data: spark.dataSource[this.pointIndex], fill: backgroundColor, textStyle: tootipArgs.textStyle, enableAnimation: false, enableRTL: spark.enableRtl, location: { x: location.x, y: location.y }, shared: false, availableSize: this.sparkline.availableSize, areaBounds: new Rect(0, 0, spark.availableSize.width, spark.availableSize.height), theme: spark.theme }); element.opacity = spark.sparkTheme.tooltipFillOpacity || element.opacity; element.appendTo(div); }; /** * Gets the formatted tooltip text for the specified Sparkline point. * * @param {string} format - The tooltip template format string. * @param {Sparkline} spark - The Sparkline instance used to resolve tooltip values. * @param {string} x - The formatted x-value text. * @param {string} y - The formatted y-value text. * @param {SparkValues} points - The Sparkline point values used to resolve tooltip tokens. * @returns {string[]} - Returns the formatted tooltip text collection. * @private */ SparklineTooltip.prototype.getFormat = function (format, spark, x, y, points) { if (isNullOrUndefined(format) || format === '') { return [y]; } var text = format; var xName = spark.xName; var yName = spark.yName; if (text.indexOf('${') !== -1) { var previous = void 0; do { previous = text; text = this.resolveSparklineTooltipTokens(text, spark, x, y, points, xName, yName); } while (text !== previous && text.indexOf('${') !== -1); } return [text]; }; /** * Resolves inline Sparkline tooltip tokens in the specified template string. * * @param {string} input - The tooltip template string that contains inline tokens to resolve. * @param {Sparkline} spark - The Sparkline instance used to resolve tooltip values. * @param {string} x - The formatted x-value text. * @param {string} y - The formatted y-value text. * @param {SparkValues} points - The Sparkline point values used to resolve tooltip tokens. * @param {string} xName - The x-value field name used in the tooltip template. * @param {string} yName - The y-value field name used in the tooltip template. * @returns {string} - Returns the tooltip template string with supported tokens resolved. * @private */ SparklineTooltip.prototype.resolveSparklineTooltipTokens = function (input, spark, x, y, points, xName, yName) { return input.replace(/\$\{([^{}]+)\}/g, this.replaceSparklineTooltipToken.bind(this, spark, x, y, points, xName, yName)); }; /** * Replaces a single inline Sparkline tooltip token with the corresponding x or y value. * * @param {Sparkline} spark - The Sparkline instance used to resolve and format tooltip values. * @param {string} x - The formatted x-value text. * @param {string} y - The formatted y-value text. * @param {SparkValues} points - The Sparkline point values used to resolve the token. * @param {string} xName - The x-value field name used in the tooltip template. * @param {string} yName - The y-value field name used in the tooltip template. * @param {string} match - The complete matched tooltip token text. * @param {string} token - The token content inside the tooltip expression. * @returns {string} - Returns the resolved tooltip token value, or the original token text when it cannot be resolved. * @private */ SparklineTooltip.prototype.replaceSparklineTooltipToken = function (spark, x, y, points, xName, yName, match, token) { var colonIndex = token.indexOf(':'); var rawPath; var inlineFormat = ''; if (colonIndex === -1) { rawPath = token; } else { rawPath = token.substring(0, colonIndex); inlineFormat = token.substring(colonIndex + 1).trim(); } // Path should not contain leading, trailing, or internal whitespace. // Format can contain whitespace, for example: ${x:MMM dd} if (rawPath !== rawPath.trim() || /\s/.test(rawPath)) { return match; } var rawValue; var fallbackText; if (rawPath === xName) { rawValue = spark.valueType === 'DateTime' ? new Date(points.xVal) : spark.valueType === 'Category' ? spark.dataSource[points.xVal][spark.xName] : points.xVal; fallbackText = x; } else if (rawPath === yName) { rawValue = points.yVal; fallbackText = y; } else { // Path does not exist, so keep original token text. return match; } return this.formatValue(rawValue, spark, inlineFormat, fallbackText).toString(); }; /** * Formats the specified Sparkline tooltip value using inline formatting, Sparkline formatting, or fallback text. * * @param {any} value - The raw tooltip value to format. * @param {Sparkline} sparkline - The Sparkline instance used to apply number or date formatting. * @param {string} inlineFormat - The optional inline format string specified in the tooltip token. * @param {string} fallbackText - The optional fallback tooltip text returned when inline formatting cannot be applied. * @returns {string | number} - Returns the formatted tooltip value. * @private */ SparklineTooltip.prototype.formatValue = function (value, sparkline, inlineFormat, fallbackText) { if (isNullOrUndefined(value)) { return String(value); } if (typeof value === 'number' && (isNaN(value) || !isFinite(value))) { return isNaN(value) ? 'NaN' : value < 0 ? '-Infinity' : 'Infinity'; } if (!isNullOrUndefined(inlineFormat) && inlineFormat !== '') { if (value instanceof Date && sparkline.intl && !this.isNumericFormat(inlineFormat)) { return sparkline.intl.getDateFormat({ format: inlineFormat })(value); } if (typeof value === 'number' && sparkline.intl && this.isNumericFormat(inlineFormat)) { return sparkline.intl.getNumberFormat({ format: inlineFormat, useGrouping: sparkline.useGroupingSeparator })(value); } return !isNullOrUndefined(fallbackText) ? fallbackText : String(value); } if (!isNullOrUndefined(fallbackText)) { return fallbackText; } if (sparkline.format && typeof value === 'number' && !isNaN(Number(value))) { var formatFunction = sparkline.intl.getNumberFormat({ format: sparkline.format, useGrouping: sparkline.useGroupingSeparator }); return formatFunction(value); } return String(value); }; /** * Checks whether the specified inline format is a numeric format. * * @param {string} format - The inline format string to validate. * @returns {boolean} - Returns true when the format is numeric; otherwise, false. * @private */ SparklineTooltip.prototype.isNumericFormat = function (format) { format = format ? format.trim() : ''; return !!format && (/^[nNpPcCeE]\d*$/.test(format) || /[0#%]/.test(format)); }; /** * To remove tracker line. * * @returns {void} */ SparklineTooltip.prototype.removeTracker = function () { var tracker = this.sparkline.element.querySelector('#' + this.sparkline.element.id + '_sparkline_tracker_g'); return tracker ? remove(tracker) : null; }; /** * To remove tooltip element. * * @returns {void} */ SparklineTooltip.prototype.removeTooltip = function () { this.pointIndex = null; var tooltip = this.sparkline.element.querySelector('#' + this.sparkline.element.id + '_sparkline_tooltip_div'); return tooltip ? remove(tooltip) : null; }; /** * Get module name. * * @returns {string} - To get the module name. */ SparklineTooltip.prototype.getModuleName = function () { return 'SparklineTooltip'; }; /** * To destroy the tooltip. * * @returns {void} */ SparklineTooltip.prototype.destroy = function () { // To remove tooltip module }; return SparklineTooltip; }()); export { SparklineTooltip };