@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
JavaScript
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 };