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.

1,042 lines 63.4 kB
var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; import { Component, Property, NotifyPropertyChanges, Browser, Complex, Event } from '@syncfusion/ej2-base'; import { EventHandler, remove, Collection, isNullOrUndefined } from '@syncfusion/ej2-base'; import { Internationalization } from '@syncfusion/ej2-base'; import { SvgRenderer, Rect, Size, measureText, TextOption } from '@syncfusion/ej2-svg-base'; import { Margin, Animation, Border } from '../common/model/base'; import { BulletChartAxis } from './renderer/bullet-axis'; import { ScaleGroup } from './renderer/scale-render'; import { redrawElement, textElement, getElement, appendChildElement, RectOption, stringToNumber, removeElement } from '../common/utils/helper'; import { getTitle, logBase } from '../common/utils/helper'; import { BulletTooltipSettings, Range, BulletLabelStyle, BulletDataLabel } from './model/bullet-base'; import { MajorTickLinesSettings, MinorTickLinesSettings } from './model/bullet-base'; import { BulletChartLegendSettings } from '../bullet-chart/model/bullet-base'; import { resized, bulletChartMouseClick } from '../common/model/constants'; import { getBulletThemeColor } from './utils/theme'; import { ExportUtils } from '../common/utils/export'; import { PrintUtils } from '../common/utils/print'; /** * bullet chart */ var BulletChart = /** @class */ (function (_super) { __extends(BulletChart, _super); /** * Constructor for creating the bullet chart. * * @param {BulletChartModel} options - Specifies the bullet chart model. * @param {string | HTMLElement} element - Specifies the element for the bullet chart. * @hidden */ function BulletChart(options, element) { var _this = _super.call(this, options, element) || this; /** @private */ _this.bulletid = 57726; /** @private */ _this.animateSeries = true; _this.padding = 5; /** @private */ _this.leftSize = 0; /** @private */ _this.rightSize = 0; /** @private */ _this.topSize = 0; /** @private */ _this.bottomSize = 0; /** @private */ _this.maxLabelSize = new Size(0, 0); _this.maxTitleSize = new Size(0, 0); /** @private */ _this.intervalDivs = [10, 5, 2, 1]; /** @private */ _this.currentLegendIndex = 0; _this.previousTargetId = ''; return _this; } /** * Initialize the event handler. * * @returns {void} */ BulletChart.prototype.preRender = function () { this.allowServerDataBinding = false; this.unWireEvents(); this.initPrivateValues(); this.setCulture(); this.wireEvents(); }; /** * To initialize the private variables. * * @returns {void} */ BulletChart.prototype.initPrivateValues = function () { this.delayRedraw = false; this.scale = new ScaleGroup(this); this.bulletAxis = new BulletChartAxis(this); if (this.element.id === '') { var collection = document.getElementsByClassName('e-BulletChart').length; this.element.id = 'BulletChart_' + this.bulletid + '_' + collection; } }; /** * Method to set culture for BulletChart. * * @returns {void} */ BulletChart.prototype.setCulture = function () { this.intl = new Internationalization(); }; /** * To Initialize the bullet chart rendering. * * @returns {void} */ BulletChart.prototype.render = function () { var _this = this; var loadEventData = { bulletChart: this, theme: this.theme, name: 'load' }; this.trigger('load', loadEventData, function () { _this.setTheme(); _this.createSvg(_this); _this.findRange(); if (_this.bulletChartLegendModule && _this.legendSettings.visible) { _this.calculateVisibleElements(); _this.bulletChartLegendModule.getLegendOptions(_this.visibleRanges); } _this.calculatePosition(); _this.renderBulletElements(); _this.trigger('loaded', { bulletChart: _this }); _this.allowServerDataBinding = true; _this.renderComplete(); }); }; /** * Theming for bullet chart. * * @returns {void} */ BulletChart.prototype.setTheme = function () { this.themeStyle = getBulletThemeColor(this.theme); if ((this.targetColor === null || this.targetColor === '#191919' || this.valueFill == null) && (this.theme.indexOf('Fluent') > -1 || this.theme.indexOf('Bootstrap5') > -1 || this.theme.indexOf('Tailwind3') > -1)) { this.valueFill = !(this.valueFill) ? (this.theme === 'FluentDark' ? '#797775' : this.theme === 'Bootstrap5' ? '#343A40' : this.theme === 'Tailwind3' ? '#1F2937' : this.theme === 'Tailwind3Dark' ? '#6B7280' : '#A19F9D') : this.valueFill; this.targetColor = (this.targetColor === '#191919') ? (this.theme === 'FluentDark' ? '#797775' : this.theme === 'Bootstrap5' ? '#343A40' : this.theme === 'Tailwind3' ? '#1F2937' : this.theme === 'Tailwind3Dark' ? '#6B7280' : '#A19F9D') : this.targetColor; } if ((this.targetColor === null || this.targetColor === '#191919' || this.valueFill == null) && (this.theme.indexOf('Material3') > -1 || this.theme.indexOf('Bootstrap5') > -1)) { this.valueFill = !(this.valueFill) ? (this.theme === 'Material3Dark' ? '#938F99' : this.theme === 'Bootstrap5Dark' ? '#343A40' : '#79747E') : this.valueFill; this.targetColor = (this.targetColor === '#191919') ? (this.theme === 'Material3Dark' ? '#938F99' : this.theme === 'Bootstrap5Dark' ? '#343A40' : '#79747E') : this.targetColor; } }; BulletChart.prototype.findRange = function () { if (!this.minimum) { this.minimum = 0; } if (!this.maximum && this.ranges.length) { this.maximum = 0; for (var i = 0; i < this.ranges.length; i++) { this.maximum = this.maximum > this.ranges[i].end ? this.maximum : this.ranges[i].end; } } if (this.maximum === null) { if (!isNullOrUndefined(this.dataSource)) { for (var i = 0; i < Object.keys(this.dataSource).length; i++) { if (this.dataSource[i][this.targetField] > this.dataSource[i][this.valueField]) { this.maximum = this.maximum > this.dataSource[i][this.targetField] ? this.maximum + this.interval : this.dataSource[i][this.targetField] + this.interval; } else { this.maximum = this.maximum > this.dataSource[i][this.valueField] ? this.maximum + this.interval : this.dataSource[i][this.valueField] + this.interval; } } } else { this.maximum = 10; } } if (!this.interval) { this.interval = this.calculateNumericNiceInterval(this.maximum - this.minimum); } }; BulletChart.prototype.getActualDesiredIntervalsCount = function (availableSize) { var size = this.orientation === 'Horizontal' ? availableSize.width : availableSize.height; var desiredIntervalsCount = (this.orientation === 'Horizontal' ? 0.533 : 1) * 3; desiredIntervalsCount = Math.max((size * (desiredIntervalsCount / 100)), 1); return desiredIntervalsCount; }; /** * Numeric Nice Interval for the axis. * * @private * @param {number} delta - The difference between maximum and minimum values. * @returns {number} - The calculated numeric nice interval for the axis. */ BulletChart.prototype.calculateNumericNiceInterval = function (delta) { var actualDesiredIntervalsCount = this.getActualDesiredIntervalsCount(this.availableSize); var niceInterval = delta / actualDesiredIntervalsCount; var minInterval = Math.pow(10, Math.floor(logBase(niceInterval, 10))); for (var _i = 0, _a = this.intervalDivs; _i < _a.length; _i++) { var interval = _a[_i]; var currentInterval = minInterval * interval; if (actualDesiredIntervalsCount < (delta / currentInterval)) { break; } niceInterval = currentInterval; } return niceInterval; }; /** * To set the left and top position for data label template for center aligned bulletchart. * * @returns {void} */ BulletChart.prototype.setSecondaryElementPosition = function () { var element = getElement(this.element.id + '_Secondary_Element'); if (!element) { return; } var rect = this.element.getBoundingClientRect(); var svgRect = getElement(this.element.id + '_svg').getBoundingClientRect(); element.style.left = Math.max(svgRect.left - rect.left, 0) + 'px'; element.style.top = Math.max(svgRect.top - rect.top, 0) + 'px'; element.style.position = 'relative'; }; /** * Method to create SVG element. */ BulletChart.prototype.createSvg = function (chart) { this.removeSvg(); chart.renderer = new SvgRenderer(chart.element.id); this.calculateAvailableSize(this); chart.svgObject = chart.renderer.createSvg({ id: chart.element.id + '_svg', width: chart.availableSize.width, height: chart.availableSize.height }); this.renderChartBackground(); }; /** * Creating a background element to the svg object. * * @returns {void} */ BulletChart.prototype.renderChartBackground = function () { var rect = new RectOption(this.element.id + '_ChartBorder', this.themeStyle.background, { width: this.border.width || 0, color: this.border.color || 'transparent' }, 1, new Rect(0, 0, this.availableSize.width, this.availableSize.height), 0, 0, '', this.border.dashArray); this.svgObject.appendChild(this.renderer.drawRectangle(rect)); }; /** * Rendering the bullet elements. * * @returns {void} */ BulletChart.prototype.renderBulletElements = function () { var scaleGroup = this.renderer.createGroup({ 'id': this.svgObject.id + '_scaleGroup' }); this.renderBulletChartTitle(); this.svgObject.appendChild(scaleGroup); this.rangeCollection = this.scale.drawScaleGroup(scaleGroup); var size = (this.orientation === 'Horizontal') ? this.initialClipRect.width : this.initialClipRect.height; var intervalValue = size / ((this.maximum - this.minimum) / this.interval); this.bulletAxis.renderMajorTickLines(intervalValue, scaleGroup); this.bulletAxis.renderMinorTickLines(intervalValue, scaleGroup); this.bulletAxis.renderAxisLabels(intervalValue, scaleGroup); this.bulletChartRect.x = (this.titlePosition === 'Left' || this.titlePosition === 'Right' || this.orientation === 'Vertical') ? this.bulletChartRect.x : 0; var elementId = this.element.id; if (this.element.tagName !== 'g') { var tooltipDiv = redrawElement(this.redraw, elementId + '_Secondary_Element') || this.createElement('div'); tooltipDiv.id = elementId + '_Secondary_Element'; appendChildElement(false, this.element, tooltipDiv, this.redraw); } if (this.tooltip.enable) { appendChildElement(false, this.svgObject, this.renderer.createGroup({ id: elementId + '_UserInteraction', style: 'pointer-events:none;' }), this.redraw); } //this.bulletAxis.renderYAxisLabels(intervalValue, scaleGroup, this.bulletChartRect); this.bindData(); this.renderDataLabel(); this.renderBulletLegend(); //this.changeOrientation(scaleGroup); this.element.appendChild(this.svgObject); this.setSecondaryElementPosition(); }; /** * To render the legend */ BulletChart.prototype.renderBulletLegend = function () { if (this.bulletChartLegendModule && this.bulletChartLegendModule.legendCollections.length) { this.bulletChartLegendModule.calTotalPage = true; var bounds = this.bulletChartLegendModule.legendBounds; this.bulletChartLegendModule.renderLegend(this, this.legendSettings, bounds); } }; /** * Handles the bullet chart resize. * * @returns {boolean} * @private */ BulletChart.prototype.bulletResize = function () { var _this = this; this.animateSeries = false; var arg = { chart: this, name: resized, currentSize: new Size(0, 0), previousSize: new Size(this.availableSize.width, this.availableSize.height) }; if (this.resizeTo) { clearTimeout(this.resizeTo); } this.resizeTo = +setTimeout(function () { if (_this.isDestroyed) { clearTimeout(_this.resizeTo); return; } _this.createSvg(_this); arg.currentSize = _this.availableSize; _this.trigger(resized, arg); _this.calculatePosition(); _this.renderBulletElements(); }, 500); return false; }; /** * Process the data values of feature and comparative measure bar. * * @returns {void} */ BulletChart.prototype.bindData = function () { if (this.dataSource != null) { this.dataCount = this.dataSource.length; this.drawMeasures(this.dataCount); } }; /** * Rendering the feature and comaparative measure bars. * * @param {number} dataCount - The count of bars to render. * @returns {void} */ BulletChart.prototype.drawMeasures = function (dataCount) { this.scale.renderFeatureBar(dataCount); this.scale.renderComparativeSymbol(dataCount); }; /** * To calculate the title bounds. * * @returns {void} */ BulletChart.prototype.calculatePosition = function () { var margin = this.margin; // Title Height; var titleHeight = 0; var subTitleHeight = 0; var titleSize = new Size(0, 0); var padding = 5; this.titleCollections = []; this.subTitleCollections = []; var maxTitlteWidth = 0; var maxTitlteHeight = 0; var maxVerticalTitlteHeight = padding; if (this.title) { this.titleCollections = getTitle(this.title, this.titleStyle, this.titleStyle.maximumTitleWidth, this.enableRtl, this.themeStyle.titleFont); titleHeight = (measureText(this.title, this.titleStyle, this.themeStyle.titleFont).height * this.titleCollections.length) + padding; for (var _i = 0, _a = this.titleCollections; _i < _a.length; _i++) { var titleText = _a[_i]; titleSize = measureText(titleText, this.titleStyle, this.themeStyle.titleFont); maxTitlteWidth = titleSize.width > maxTitlteWidth ? titleSize.width : maxTitlteWidth; maxTitlteHeight = titleSize.height > maxTitlteHeight ? titleSize.height : maxTitlteHeight; } maxVerticalTitlteHeight += maxTitlteHeight; this.subTitleCollections = getTitle(this.subtitle, this.subtitleStyle, this.titleStyle.maximumTitleWidth, this.enableRtl); if (this.subtitle) { for (var _b = 0, _c = this.subTitleCollections; _b < _c.length; _b++) { var subText = _c[_b]; titleSize = measureText(subText, this.subtitleStyle, this.themeStyle.subTitleFont); maxTitlteWidth = titleSize.width > maxTitlteWidth ? titleSize.width : maxTitlteWidth; maxTitlteHeight = titleSize.height > maxTitlteHeight ? titleSize.height : maxTitlteHeight; } subTitleHeight = (measureText(this.subtitle, this.subtitleStyle, this.themeStyle.subTitleFont).height * this.subTitleCollections.length) + padding; maxVerticalTitlteHeight += maxTitlteHeight; } } this.maxTitleSize = new Size(maxTitlteWidth, this.orientation === 'Vertical' ? maxVerticalTitlteHeight : maxTitlteHeight); this.maxLabelSize = this.getMaxLabelWidth(); this.initialClipRect = this.getBulletBounds((this.orientation === 'Vertical' ? maxVerticalTitlteHeight : maxTitlteWidth), titleHeight, subTitleHeight, margin); this.bulletChartRect = new Rect(this.initialClipRect.x, this.initialClipRect.y, this.initialClipRect.width, this.initialClipRect.height); if (this.bulletChartLegendModule) { this.bulletChartLegendModule.calculateLegendBounds(this.initialClipRect, this.availableSize, this.maxLabelSize); } }; /** * Calculate the rect values based on title position. * * @param {number} maxTitlteWidth - The maximum width of the title. * @param {number} titleHeight - The height of the title. * @param {number} subTitleHeight - The height of the subtitle. * @param {MarginModel} margin - The margin settings. * @returns {Rect} - The calculated rect values. * @private */ BulletChart.prototype.getBulletBounds = function (maxTitlteWidth, titleHeight, subTitleHeight, margin) { var padding = 5; var rect = new Rect(0, 0, 0, 0); var enableRtl = this.enableRtl; var labelSpace = (this.labelPosition === this.tickPosition) ? padding : 0; var tickSize = ((this.tickPosition === 'Inside') ? 0 : (this.majorTickLines.height)); var labelSize = ((this.labelPosition === 'Inside') ? 0 : padding + ((this.tickPosition === 'Outside') ? 0 : (measureText(this.maximum.toString(), this.labelStyle, this.themeStyle.dataLabelFont).height))); var topAxisLabel = 0; var bottomAxisLabel = 0; var leftAxisLabel = 0; var rightAxisLabel = 0; var topCategory = 0; var bottomCategory = 0; var leftCategory = 0; var rightCategory = 0; var title = maxTitlteWidth; var format = this.bulletAxis.getFormat(this); var isCustomFormat = format.match('{value}') !== null; this.bulletAxis.format = this.intl.getNumberFormat({ format: isCustomFormat ? '' : format, useGrouping: this.enableGroupSeparator }); var formatted = measureText(this.bulletAxis.formatValue(this.bulletAxis, isCustomFormat, format, this.maximum), this.labelStyle, this.themeStyle.axisLabelFont).width; var categoryLabelSize; if (this.orientation === 'Horizontal') { categoryLabelSize = this.maxLabelSize.width; topAxisLabel = (this.opposedPosition) ? tickSize + labelSize + labelSpace : 0; bottomAxisLabel = (!this.opposedPosition) ? tickSize + labelSize + labelSpace : 0; leftCategory = ((categoryLabelSize && !enableRtl) ? (categoryLabelSize) : 0); leftCategory += (title && this.titlePosition === 'Left') ? padding * 3 : 0; rightCategory = ((categoryLabelSize && enableRtl) ? (categoryLabelSize) : 0); rightCategory += (title && this.titlePosition === 'Right') ? padding : 0; } else { categoryLabelSize = this.maxLabelSize.height; rightAxisLabel = (this.opposedPosition) ? tickSize + labelSpace : 0; rightAxisLabel += (this.opposedPosition && this.labelPosition !== 'Inside') ? formatted : 0; leftAxisLabel = (!this.opposedPosition) ? tickSize + labelSpace : 0; leftAxisLabel += (!this.opposedPosition && this.labelPosition !== 'Inside') ? formatted : 0; topCategory = ((categoryLabelSize && enableRtl) ? (categoryLabelSize + padding) : 0); bottomCategory = ((categoryLabelSize && !enableRtl) ? (categoryLabelSize + padding) : 0); } switch (this.titlePosition) { case 'Left': rect.x = margin.left + title + leftCategory + leftAxisLabel; rect.width = (this.availableSize.width - margin.right - rect.x - rightCategory - rightAxisLabel) < 0 ? 0 : this.availableSize.width - margin.right - rect.x - rightCategory - rightAxisLabel; rect.y = margin.top + topAxisLabel + topCategory; rect.height = (this.availableSize.height - rect.y - margin.bottom - bottomAxisLabel - bottomCategory) < 0 ? 0 : this.availableSize.height - rect.y - margin.bottom - bottomAxisLabel - bottomCategory; break; case 'Right': rect.x = margin.left + leftCategory + leftAxisLabel; rect.width = (this.availableSize.width - rightAxisLabel - margin.right - rect.x - (title + padding) - rightCategory) < 0 ? 0 : this.availableSize.width - rightAxisLabel - margin.right - rect.x - (title + padding) - rightCategory; rect.y = margin.top + topAxisLabel + topCategory; rect.height = (this.availableSize.height - rect.y - margin.bottom - bottomAxisLabel - bottomCategory) < 0 ? 0 : this.availableSize.height - rect.y - margin.bottom - bottomAxisLabel - bottomCategory; break; case 'Top': rect.x = margin.left + leftAxisLabel + leftCategory; rect.width = (this.availableSize.width - margin.right - rect.x - rightCategory - rightAxisLabel) < 0 ? 0 : this.availableSize.width - margin.right - rect.x - rightCategory - rightAxisLabel; rect.y = margin.top + (titleHeight + subTitleHeight) + topAxisLabel + topCategory; rect.height = (this.availableSize.height - rect.y - margin.bottom - bottomAxisLabel - bottomCategory) < 0 ? 0 : this.availableSize.height - rect.y - margin.bottom - bottomAxisLabel - bottomCategory; break; case 'Bottom': rect.x = margin.left + leftAxisLabel + leftCategory; rect.y = margin.top + topAxisLabel + topCategory; rect.width = (this.availableSize.width - margin.right - rect.x - rightCategory - rightAxisLabel) < 0 ? 0 : this.availableSize.width - margin.right - rect.x - rightCategory - rightAxisLabel; rect.height = (this.availableSize.height - rect.y - bottomCategory - margin.bottom - bottomAxisLabel - (titleHeight + subTitleHeight)) < 0 ? 0 : this.availableSize.height - rect.y - bottomCategory - margin.bottom - bottomAxisLabel - (titleHeight + subTitleHeight); break; } return rect; }; /** * Calculate maximum label width for category values. * * @private * @returns {Size} To get a label width */ BulletChart.prototype.getMaxLabelWidth = function () { this.maxLabelSize = new Size(0, 0); if (!this.categoryField) { return this.maxLabelSize; } var label; if (!isNullOrUndefined(this.dataSource)) { for (var i = 0, len = Object.keys(this.dataSource).length; i < len; i++) { label = measureText((this.dataSource[i][this.categoryField] || ''), this.categoryLabelStyle, this.themeStyle.axisLabelFont); if (label.width > this.maxLabelSize.width) { this.maxLabelSize.width = label.width; } if (label.height > this.maxLabelSize.height) { this.maxLabelSize.height = label.height; } } } return this.maxLabelSize; }; BulletChart.prototype.calculateVisibleElements = function () { var range; var rangeCollection = this.ranges; this.visibleRanges = []; for (var i = 0, len = rangeCollection.length; i < len; i++) { range = rangeCollection[i]; range.index = i; this.visibleRanges.push(range); rangeCollection[i] = range; } }; /** * To render the title of the bullet chart. * * @returns {void} */ BulletChart.prototype.renderBulletChartTitle = function () { var margin = this.margin; var x = 0; var y = 0; var padding = 5; var anchor = 'middle'; var transform = ''; var alignment = this.titleStyle.textAlignment; var elementSize = measureText(this.title, this.titleStyle, this.themeStyle.titleFont); var subTitleSize = (this.subtitle) ? measureText(this.subtitle, this.subtitleStyle, this.themeStyle.subTitleFont) : new Size(0, 0); if (this.title) { if (this.orientation === 'Horizontal') { switch (this.titlePosition) { case 'Top': x = this.findHorizontalAlignment(margin); anchor = (alignment === 'Far') ? 'end' : ((alignment === 'Near') ? 'start' : 'middle'); y = margin.top + elementSize.height / 2 + padding; break; case 'Bottom': x = this.findHorizontalAlignment(margin); anchor = (alignment === 'Far') ? 'end' : ((alignment === 'Near') ? 'start' : 'middle'); y = this.availableSize.height - margin.bottom - elementSize.height / 3 + padding * 2 - ((subTitleSize.height) ? subTitleSize.height + padding : 0); break; case 'Left': anchor = 'end'; x = margin.left + this.maxTitleSize.width; y = (this.margin.top + (this.availableSize.height) / 2 - elementSize.height / 3) - ((subTitleSize.height) ? subTitleSize.height : 0); break; case 'Right': anchor = 'start'; x = (this.availableSize.width - margin.right - this.maxTitleSize.width + padding); y = (this.margin.top + (this.availableSize.height) / 2 - elementSize.height / 3) - ((subTitleSize.height) ? subTitleSize.height : 0); break; } } else { switch (this.titlePosition) { case 'Top': x = (this.availableSize.width) / 2 + padding * 2; y = this.margin.top + elementSize.height / 2 + padding; break; case 'Bottom': x = (this.availableSize.width) / 2; y = this.availableSize.height - this.margin.bottom - elementSize.height / 3 + padding * 2 - ((subTitleSize.height) ? subTitleSize.height + padding : 0); break; case 'Left': y = this.findVerticalAlignment(margin); anchor = (alignment === 'Far') ? 'start' : ((alignment === 'Near') ? 'end' : 'middle'); x = margin.left; break; case 'Right': x = (this.availableSize.width - margin.right - elementSize.height / 3); anchor = (alignment === 'Far') ? 'start' : ((alignment === 'Near') ? 'end' : 'middle'); y = this.findVerticalAlignment(margin); break; } transform = (this.titlePosition === 'Left') ? 'rotate(-90,' + x + ',' + y + ')' : ((this.titlePosition === 'Right') ? 'rotate(90,' + x + ',' + y + ')' : ''); } var options = new TextOption(this.element.id + '_BulletChartTitle', x, y, anchor, this.titleCollections, transform, 'auto'); var element = textElement(this.renderer, options, this.titleStyle, this.titleStyle.color || this.themeStyle.titleFont.color, this.svgObject, null, null, null, null, null, null, null, null, null, null, this.themeStyle.titleFont); if (element) { element.setAttribute('aria-label', this.title + '. Syncfusion interactive chart.'); element.setAttribute('tabindex', '0'); element.style.outline = 'none'; element.setAttribute('role', 'img'); } if (this.subtitle) { this.renderBulletChartSubTitle(x, y, anchor); } } }; /** * To render the data label for bullet chart. * * @returns {void} */ BulletChart.prototype.renderDataLabel = function () { var x = 0; var y = 0; var anchor; var transform = ''; var enableRtl = this.enableRtl; var data; var featureBounds; var alignment = this.dataLabel.labelStyle.textAlignment; var format = this.labelFormat ? this.labelFormat : ''; var isCustomFormat = format.match('{value}') !== null; if (this.dataLabel.enable) { for (var i = 0, len = Object.keys(this.dataSource).length; i < len; i++) { data = this.dataSource[i]; featureBounds = this.scale.featureBarBounds[i]; var labelText = (data[this.valueField]).toString(); this.format = this.intl.getNumberFormat({ format: isCustomFormat ? '' : format, useGrouping: this.enableGroupSeparator }); labelText = isCustomFormat ? format.replace('{value}', this.format(labelText)) : labelText; var labelSize = measureText(labelText, this.dataLabel.labelStyle, this.themeStyle.axisLabelFont); var textWidth = labelSize['width']; var textHeight = labelSize['height']; if (this.orientation === 'Horizontal') { anchor = this.type === 'Rect' ? 'end' : (enableRtl ? 'end' : 'start'); x = this.findTextAlignment(featureBounds, textWidth, alignment); if (x - textWidth < this.initialClipRect.x) { anchor = 'start'; } if (x > this.initialClipRect.width) { x -= textWidth; } y = featureBounds.y + featureBounds.height / 2; } else { anchor = 'middle'; x = featureBounds.y + featureBounds.height / 2; y = this.findTextAlignment(featureBounds, textWidth, alignment); if (y + (textHeight / 2) > this.initialClipRect.height + this.initialClipRect.y) { y = y - (textHeight / 3); } } var labelOptions = new TextOption(this.element.id + '_DataLabel_' + i, x, y, anchor, labelText, transform, 'middle'); textElement(this.renderer, labelOptions, this.dataLabel.labelStyle, this.dataLabel.labelStyle.color || this.themeStyle.dataLabelFont.color, this.svgObject, null, null, null, null, null, null, null, null, null, null, this.themeStyle.dataLabelFont); } } }; BulletChart.prototype.findTextAlignment = function (featureBounds, textWidth, alignment) { var elementSpacing = 10; var x = 0; switch (alignment) { case 'Center': x = featureBounds.x + featureBounds.width / 2; break; case 'Near': x = featureBounds.x + (this.orientation === 'Horizontal' ? (this.enableRtl ? featureBounds.width - elementSpacing / 2 : elementSpacing / 2) : (this.enableRtl ? elementSpacing : featureBounds.width)); break; case 'Far': x = featureBounds.x + (this.orientation === 'Horizontal' ? ((this.enableRtl ? (this.type === 'Rect' ? textWidth + elementSpacing : -elementSpacing) : featureBounds.width) + (this.type === 'Rect' ? -elementSpacing / 2 : elementSpacing / 2)) : (this.enableRtl ? featureBounds.width + (this.type === 'Rect' ? -elementSpacing : elementSpacing) : 0) + (this.type === 'Rect' ? elementSpacing : -elementSpacing)); break; } return x; }; BulletChart.prototype.findHorizontalAlignment = function (margin) { var x = 0; switch (this.titleStyle.textAlignment) { case 'Center': x = (this.availableSize.width - margin.left - margin.right) / 2; break; case 'Near': x = margin.left; break; case 'Far': x = this.availableSize.width - margin.right; break; } return x; }; BulletChart.prototype.findVerticalAlignment = function (margin) { var y = 0; switch (this.titleStyle.textAlignment) { case 'Center': y = (this.availableSize.height - margin.top - margin.bottom) / 2; break; case 'Near': y = margin.top; break; case 'Far': y = this.availableSize.height - margin.bottom; break; } return y; }; /** * To render the sub title of the bullet chart. * * @param {number} x - The x-coordinate of the sub title. * @param {number} y - The y-coordinate of the sub title. * @param {string} anchor - The anchor position of the sub title. * @returns {void} */ BulletChart.prototype.renderBulletChartSubTitle = function (x, y, anchor) { var margin = this.margin; var padding = 5; var transform = ''; var elementSize = measureText(this.subtitle, this.subtitleStyle, this.themeStyle.subTitleFont); if (this.orientation === 'Horizontal') { switch (this.titlePosition) { case 'Top': y = y + elementSize.height + padding / 2; break; case 'Bottom': y = this.availableSize.height - margin.bottom - elementSize.height / 3 + padding; break; case 'Left': y = y + elementSize.height + padding / 2; break; case 'Right': y = y + elementSize.height + padding / 2; break; } } else { switch (this.titlePosition) { case 'Top': y = y + elementSize.height + padding / 2; break; case 'Bottom': y = this.availableSize.height - margin.bottom - elementSize.height / 3 + padding; break; case 'Left': x += elementSize.height + padding / 2; break; case 'Right': x -= elementSize.height + padding / 2; break; } transform = (this.titlePosition === 'Left') ? 'rotate(-90,' + x + ',' + y + ')' : ((this.titlePosition === 'Right') ? 'rotate(90,' + x + ',' + y + ')' : ''); } var subTitleOptions = new TextOption(this.element.id + '_BulletChartSubTitle', x, y, anchor, this.subTitleCollections, transform, 'auto'); var element = textElement(this.renderer, subTitleOptions, this.subtitleStyle, this.subtitleStyle.color || this.themeStyle.subTitleFont.color, this.svgObject, null, null, null, null, null, null, null, null, null, null, this.themeStyle.subTitleFont); if (element) { element.setAttribute('aria-label', this.subtitle); element.setAttribute('tabindex', '0'); element.style.outline = 'none'; element.setAttribute('role', 'img'); } }; /** * To calculate the available size and width of the container */ BulletChart.prototype.calculateAvailableSize = function (bulletChart) { var containerWidth = this.element.clientWidth || this.element.offsetWidth || 200; var height = (this.orientation === 'Vertical') ? 450 : ((this.titlePosition === 'Left' || this.titlePosition === 'Right') ? 83 : 126); var containerHeight = this.element.clientHeight || height; bulletChart.availableSize = new Size(stringToNumber(bulletChart.width, containerWidth) || containerWidth, stringToNumber(bulletChart.height, containerHeight) || containerHeight); }; BulletChart.prototype.removeSvg = function () { var svgElement = document.getElementById(this.element.id + '_svg'); if (svgElement) { remove(svgElement); } }; BulletChart.prototype.getPersistData = function () { var keyEntity = ['loaded']; return this.addOnPersist(keyEntity); }; /** Wire, UnWire and Event releated calculation Started here */ /** * Method to un-bind events for bullet chart. * * @returns {void} */ BulletChart.prototype.unWireEvents = function () { /** Find the Events type */ var startEvent = Browser.touchStartEvent; var moveEvent = Browser.touchMoveEvent; var cancelEvent = Browser.isPointer ? 'pointerleave' : 'mouseleave'; /** UnBind the Event handler */ EventHandler.remove(this.element, startEvent, this.bulletMouseDown); EventHandler.remove(this.element, moveEvent, this.bulletMouseMove); EventHandler.remove(this.element, cancelEvent, this.bulletMouseLeave); EventHandler.remove(this.element, 'click', this.bulletChartOnMouseClick); EventHandler.remove(this.element, 'keyup', this.chartKeyUp); EventHandler.remove(this.element, 'keydown', this.chartKeyDown); window.removeEventListener((Browser.isTouch && ('orientation' in window && 'onorientationchange' in window)) ? 'orientationchange' : 'resize', this.resizeBound); }; /** * Method to bind events for bullet chart. * * @returns {void} */ BulletChart.prototype.wireEvents = function () { var cancelEvent = Browser.isPointer ? 'pointerleave' : 'mouseleave'; /** Bind the Event handler */ EventHandler.add(this.element, Browser.touchMoveEvent, this.bulletMouseMove, this); EventHandler.add(this.element, cancelEvent, this.bulletMouseLeave, this); EventHandler.add(this.element, Browser.touchStartEvent, this.bulletMouseDown, this); EventHandler.add(this.element, 'click', this.bulletChartOnMouseClick, this); EventHandler.add(this.element, 'keyup', this.chartKeyUp, this); EventHandler.add(this.element, 'keydown', this.chartKeyDown, this); this.resizeBound = this.bulletResize.bind(this); window.addEventListener((Browser.isTouch && ('orientation' in window && 'onorientationchange' in window)) ? 'orientationchange' : 'resize', this.resizeBound); /** Apply the style for chart */ this.setStyle(this.element); }; /** * Handles the keyboard onkeydown on bullet chart. * * @param {KeyboardEvent} e - The keyboard event. * @returns {void} - returns nothing * @private */ BulletChart.prototype.chartKeyDown = function (e) { if (e.code === 'Tab') { this.removeNavigationStyle(); } }; BulletChart.prototype.setStyle = function (element) { element.style.position = 'relative'; element.style.display = 'block'; }; /** * Handles the mouse move on the bullet chart. * * @private * @param {PointerEvent} e - The pointer event. * @returns {void} */ BulletChart.prototype.bulletMouseMove = function (e) { var pageX = e.clientX; var pageY = e.clientY; this.setPointMouseXY(pageX, pageY); var targetId = e.target.id; var targetClass = e.target.className['baseVal']; if (targetClass !== this.svgObject.id + '_FeatureMeasure' || this.svgObject.id + '_ComparativeMeasure') { if (!isNullOrUndefined(this.dataSource)) { for (var i = 0; i < Object.keys(this.dataSource).length; i++) { document.getElementById(this.svgObject.id + '_FeatureMeasure_' + i).setAttribute('opacity', '1'); document.getElementById(this.svgObject.id + '_ComparativeMeasure_' + i).setAttribute('opacity', '1'); } } } if (!this.isTouchEvent(e)) { var id = 'tooltipDiv' + this.element.id; var tooltipDiv = document.getElementById(id); if (tooltipDiv) { if (this.isReact) { this.clearTemplate(); } remove(tooltipDiv); } if (this.bulletTooltipModule) { this.bulletTooltipModule._elementTooltip(e, targetClass, targetId, this.mouseX); this.bulletTooltipModule._displayTooltip(e, targetClass, targetId, this.mouseX, this.mouseY); } } }; /** * To find mouse x, y for aligned bullet chart element svg position. * * @param {number} pageX - The x-coordinate of the mouse position on the page. * @param {number} pageY - The y-coordinate of the mouse position on the page. * @returns {void} */ BulletChart.prototype.setPointMouseXY = function (pageX, pageY) { var svgClientRect = getElement(this.svgObject.id).getBoundingClientRect(); var elemntClientRect = this.element.getBoundingClientRect(); this.mouseX = (pageX - elemntClientRect.left) - Math.max(svgClientRect.left - elemntClientRect.left, 0); this.mouseY = (pageY - elemntClientRect.top) - Math.max(svgClientRect.top - elemntClientRect.top, 0); }; /** * Handles the mouse leave on the bullet chart. * * @private * @param {PointerEvent} e - The pointer event. * @returns {void} */ BulletChart.prototype.bulletMouseLeave = function (e) { if (!this.isTouchEvent(e)) { var tooltipDiv = document.getElementById('.tooltipDiv' + this.element.id); if (tooltipDiv) { if (this.isReact) { this.clearTemplate(); } remove(tooltipDiv); } } }; /** * Handles the touch event. * * @param {PointerEvent} event - The pointer event. * @returns {boolean} - Touch event. * @private */ BulletChart.prototype.isTouchEvent = function (event) { if ((event.pointerType === 'touch') || (event.type.indexOf('touch') > -1)) { return true; } return false; }; /** * Handles the mouse down on the bullet chart. * * @private * @param {PointerEvent} e - The pointer event. * @returns {void} */ BulletChart.prototype.bulletMouseDown = function (e) { var pageX; var pageY; var touchArg; if (e.type === 'touchstart') { this.isTouch = true; touchArg = e; pageX = touchArg.changedTouches[0].clientX; pageY = touchArg.changedTouches[0].clientY; } else { this.isTouch = e.pointerType === 'touch'; pageX = e.clientX; pageY = e.clientY; } this.setPointMouseXY(pageX, pageY); if (this.isTouchEvent(e)) { if (this.isReact) { this.clearTemplate(); } var Element_1 = document.getElementById(('tooltipDiv' + this.element.id)); if (Element_1) { remove(Element_1); } var targetId = e.target.id; var targetClass = e.target.className['baseVal']; if (this.bulletTooltipModule) { this.bulletTooltipModule._elementTooltip(e, targetClass, targetId, this.mouseX); this.bulletTooltipModule._displayTooltip(e, targetClass, targetId, this.mouseX, this.mouseY); } } this.removeNavigationStyle(); }; /** * Handles the mouse click on bullet chart. * * @param {PointerEvent | TouchEvent} e - The pointer or touch event. * @returns {boolean} - Mouse click of bullet chart. * @private */ BulletChart.prototype.bulletChartOnMouseClick = function (e) { var element = e.target; this.trigger(bulletChartMouseClick, { target: element.id, x: this.mouseX, y: this.mouseY }); this.notify('click', e); this.removeNavigationStyle(); return false; }; /** * Handles the print method for bullet chart control. * * @param {string[] | string | Element} id - The id of the bullet chart to be printed on the page. * @returns {void} */ BulletChart.prototype.print = function (id) { new PrintUtils(this).print(id); }; /** * Handles the export method for bullet chart control. * * @param {ExportType} type - Type of the export. * @param {string} fileName - File name for exporting. * @param {PdfPageOrientation} orientation - Orientation of the export. * @param {(Chart | AccumulationChart | RangeNavigator | BulletChart)[]} controls - To mention the exporting chart. * @param {number} width - Width of the export. * @param {number} height - Height of the export. * @param {boolean} isVertical - Whether the export is in vertical orientation. * @returns {void} */ BulletChart.prototype.export = function (type, fileName, orientation, controls, width, height, isVertical) { controls = controls ? controls : [this]; new ExportUtils(this).export(type, fileName, orientation, controls, width, height, isVertical); }; /** * Handles the keyboard onkeydown on bullet chart. * * @param {KeyboardEvent} e - The keyboard event. * @returns {boolean} - false * @private */ BulletChart.prototype.chartKeyUp = function (e) { var targetId = e.target['id']; var groupElement; var targetElement = e.target; var legendElement = getElement(this.element.id + '_chart_legend_translate_g'); this.removeNavigationStyle(); if (e.code === 'Tab') { this.setNavigationStyle(targetId); } if (legendElement) { var firstChild = legendElement.firstElementChild; var className = firstChild.getAttribute('class'); if (className && className.indexOf('e-bullet-chart-focused') === -1) { className = className + ' e-bullet-chart-focused'; } else if (!className) { className = 'e-bullet-chart-focused'; } firstChild.setAttribute('class', className); } if (e.code === 'Tab') { if (this.previousTargetId !== '') { if (this.previousTargetId.indexOf('_chart_legend_g_') > -1 && targetId.indexOf('_chart_legend_g_') === -1) { groupElement = getElement(this.element.id + '_chart_legend_translate_g'); this.setTabIndex(groupElement.children[this.currentLegendIndex], groupElement.firstElementChild); } } this.previousTargetId = targetId; } else if (e.code.indexOf('Arrow') > -1) { e.preventDefault(); if ((targetId.indexOf('_chart_legend_') > -1)) { var legendElement_1 = targetElement.parentElement.children; legendElement_1[this.currentLegendIndex].removeAttribute('tabindex'); this.currentLegendIndex += (e.code === 'ArrowUp' || e.code === 'ArrowRight') ? +1 : -1; this.currentLegendIndex = this.getActualIndex(this.currentLegendIndex, legendElement_1.length); var currentLegend = legendElement_1[this.currentLegendIndex]; this.focusChild(currentLegend); this.removeNavigationStyle(); this.setNavigationStyle(currentLegend.id); targetId = currentLegend.children[1].id; } } return false;