UNPKG

@syncfusion/ej2-heatmap

Version:

Feature rich data visulization control used to visualize the matrix data where the individual values are represented as colors

1,046 lines 102 kB
/** * Heat Map Component */ 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, Internationalization, Complex, isNullOrUndefined, SanitizeHtmlHelper } from '@syncfusion/ej2-base'; import { remove, Event, EventHandler, Touch } from '@syncfusion/ej2-base'; // eslint-disable-next-line import { Browser } from '@syncfusion/ej2-base'; import { SvgRenderer, CanvasRenderer } from '@syncfusion/ej2-svg-base'; import { Size, stringToNumber, RectOption, Rect, TextBasic, measureText, removeMeasureElement } from './utils/helper'; import { DrawSvgCanvas, TextOption, titlePositionX, getTitle, showTooltip, getElement, SelectedCellDetails } from './utils/helper'; import { removeElement, CanvasTooltip, getTooltipText } from './utils/helper'; import { Margin, Title } from './model/base'; import { Theme, getThemeColor } from './model/theme'; import { Axis } from './axis/axis'; import { AxisHelper } from './axis/axis-helpers'; import { Series, CellSettings } from './series/series'; import { PaletteSettings, CellColor } from './utils/colorMapping'; import { TooltipSettings } from './utils/tooltip'; import { TwoDimensional } from './datasource/twodimensional'; import { LegendSettings } from '../heatmap/legend/legend'; import { Data } from './datasource/adaptor'; import { ExportUtils } from '../heatmap/utils/export'; /** * Represents the heatmap control. This is used to customize the properties of the heatmap in order to visualize two-dimensional data, with values represented by gradient or solid color variations. * ```html * <div id="container"/> * <script> * var heatmapObj = new HeatMap(); * heatmapObj.appendTo("#container"); * </script> * ``` */ var HeatMap = /** @class */ (function (_super) { __extends(HeatMap, _super); function HeatMap() { /** * Sets and gets the width of the heatmap. The width of the heatmap accepts pixel or percentage values given in string format. * * If specified as '100%, heatmap renders to the full width of its parent element. * * @default null */ var _this = _super !== null && _super.apply(this, arguments) || this; /** @private */ _this.enableCanvasRendering = false; /** @private */ _this.isColorRange = false; /** @private */ _this.isCellTapHold = false; /** @private */ _this.selectedCellCount = 0; /** @private */ _this.toggleValue = []; /** @private */ _this.legendOnLoad = true; /** @private */ _this.resizing = false; /** @private */ _this.rendering = true; /** @private */ _this.multiSelection = false; /** @private */ _this.rectSelected = false; /** @private */ _this.previousSelectedCellsRect = []; /** @private */ _this.multiCellCollection = []; /** @private */ _this.selectedMultiCellCollection = []; /** @private */ _this.tempMultiCellCollection = []; /** * @private */ _this.tooltipCollection = []; /** * @private */ _this.isCellData = false; return _this; } HeatMap.prototype.preRender = function () { this.initPrivateVariable(); this.unWireEvents(); this.wireEvents(); }; /** * This method is used to perform the export functionality for the heatmap. * * @param {ExportType} type - Specifies the type of the exported file. * @param {string} fileName - Specifies the file name for the exported file. * @param {PdfPageOrientation} orientation - Specifies the orientation for the exported PDF document. */ HeatMap.prototype.export = function (type, fileName, orientation) { var exportMap = new ExportUtils(this); exportMap.export(type, fileName, orientation); }; HeatMap.prototype.initPrivateVariable = function () { this.rendering = true; if (this.element.id === '') { var collection = document.getElementsByClassName('e-heatmap').length; var elementid = '_' + collection; while (document.getElementById(elementid)) { collection++; elementid = 'heatmap_' + collection; } this.element.id = 'heatmap_' + collection; } this.renderer = new SvgRenderer(this.element.id); this.canvasRenderer = new CanvasRenderer(this.element.id); this.secondaryCanvasRenderer = new CanvasRenderer(this.element.id + '_secondary'); this.heatMapAxis = new AxisHelper(this); this.heatMapSeries = new Series(this); this.drawSvgCanvas = new DrawSvgCanvas(this); this.twoDimensional = new TwoDimensional(this); this.cellColor = new CellColor(this); this.tempRectHoverClass = ''; this.tempTooltipRectId = ''; this.setCulture(); }; /** * Method to set culture for heatmap */ HeatMap.prototype.setCulture = function () { this.intl = new Internationalization(); }; HeatMap.prototype.render = function () { this.horizontalGradient = this.legendSettings.position === 'Bottom' || this.legendSettings.position === 'Top'; this.updateBubbleHelperProperty(); this.trigger('load', { heatmap: this }); if (this.theme === 'TailwindDark' || this.theme === 'Tailwind') { var textSettings = { title: { textStyle: { size: '12px', fontFamily: 'Inter', fontWeight: '500' } }, textStyle: { size: '12px', fontFamily: 'Inter' } }; this.setProperties({ titleSettings: { textStyle: { size: '14px', fontFamily: 'Inter' } } }, true); this.setProperties({ legendSettings: textSettings }, true); this.setProperties({ xAxis: textSettings }, true); this.setProperties({ yAxis: textSettings }, true); this.setProperties({ cellSettings: { textStyle: { fontFamily: 'Inter' } } }, true); } if (this.theme === 'Tailwind3Dark' || this.theme === 'Tailwind3') { var textSettings = { title: { textStyle: { size: '12px', fontFamily: 'Inter', fontWeight: '500' } }, textStyle: { size: '12px', fontFamily: 'Inter', fontWeight: '500' } }; this.setProperties({ titleSettings: { textStyle: { size: '14px', fontFamily: 'Inter', fontWeight: '600' } } }, true); this.setProperties({ legendSettings: textSettings }, true); this.setProperties({ xAxis: { title: { textStyle: { size: '12px', fontFamily: 'Inter', fontWeight: '500' } }, textStyle: { size: '12px', fontFamily: 'Inter', fontWeight: '400' } } }, true); this.setProperties({ yAxis: { title: { textStyle: { size: '12px', fontFamily: 'Inter', fontWeight: '500' } }, textStyle: { size: '12px', fontFamily: 'Inter', fontWeight: '400' } } }, true); this.setProperties({ cellSettings: { textStyle: { fontFamily: 'Inter', fontWeight: '400' } } }, true); } if (this.theme === 'Material3' || this.theme === 'Material3Dark') { var textSettings = { title: { textStyle: { size: '14px', fontFamily: 'Roboto', fontWeight: '500' } }, textStyle: { size: '12px', fontFamily: 'Roboto', fontWeight: '400' } }; this.setProperties({ titleSettings: { textStyle: { size: '16px', fontFamily: 'Roboto' } } }, true); this.setProperties({ legendSettings: textSettings }, true); this.setProperties({ xAxis: textSettings }, true); this.setProperties({ yAxis: textSettings }, true); this.setProperties({ cellSettings: { textStyle: { fontFamily: 'Roboto', fontWeight: '400' } } }, true); } if (this.theme === 'Bootstrap5' || this.theme === 'Bootstrap5Dark') { var textSettings = { title: { textStyle: { size: '12px', fontFamily: 'Segoe UI', fontWeight: '400' } }, textStyle: { size: '12px', fontFamily: 'Segoe UI', fontWeight: '400' } }; this.setProperties({ titleSettings: { textStyle: { size: '14px', fontFamily: 'Segoe UI', fontWeight: '400' } } }, true); this.setProperties({ legendSettings: textSettings }, true); this.setProperties({ xAxis: textSettings }, true); this.setProperties({ yAxis: textSettings }, true); this.setProperties({ cellSettings: { textStyle: { size: '10px', fontWeight: '400', fontFamily: 'Segoe UI' } } }, true); } if (this.theme === 'Fluent' || this.theme === 'FluentDark') { var textSettings = { title: { textStyle: { size: '12px', fontFamily: '"Segoe UI", -apple-system, BlinkMacSystemFont, "Roboto", "Helvetica Neue", sans-serif', fontWeight: '500' } }, textStyle: { size: '12px', fontFamily: 'system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"' } }; this.setProperties({ titleSettings: { textStyle: { size: '16px', fontFamily: '"Segoe UI", -apple-system, BlinkMacSystemFont, "Roboto", "Helvetica Neue", sans-serif' } } }, true); this.setProperties({ legendSettings: textSettings }, true); this.setProperties({ xAxis: textSettings }, true); this.setProperties({ yAxis: textSettings }, true); this.setProperties({ cellSettings: { textStyle: { fontFamily: '"Segoe UI", -apple-system, BlinkMacSystemFont, "Roboto", "Helvetica Neue", sans-serif' } } }, true); } if (this.theme === 'Fluent2' || this.theme === 'Fluent2Dark' || this.theme === 'Fluent2HighContrast') { var textSettings = { title: { textStyle: { size: '12px', fontFamily: 'Segoe UI', fontWeight: '400' } }, textStyle: { size: '12px', fontFamily: 'Segoe UI', fontWeight: '400' } }; this.setProperties({ titleSettings: { textStyle: { size: '14px', fontFamily: 'Segoe UI', fontWeight: '600' } } }, true); this.setProperties({ legendSettings: textSettings }, true); this.setProperties({ xAxis: textSettings }, true); this.setProperties({ yAxis: textSettings }, true); this.setProperties({ cellSettings: { textStyle: { size: '10px', fontWeight: '400', fontFamily: 'Segoe UI' } } }, true); } this.initAxis(); this.processInitData(); this.setTheme(); this.calculateMaxLength(); this.heatMapAxis.calculateVisibleLabels(); this.twoDimensional.processDataSource(this.completeAdaptDataSource); this.createSvg(); this.cellColor.getColorCollection(); this.calculateBounds(); this.renderElements(); this.appendSvgObject(); if (this.tooltipModule) { this.tooltipModule.showHideTooltip(false); } this.renderComplete(); this.trigger('loaded', ({ heatmap: this })); }; /** * To re-calculate the datasource while changing datasource property dynamically. * * @private */ HeatMap.prototype.reRenderDatasource = function () { this.dataSourceMinValue = null; this.dataSourceMaxValue = null; this.processInitData(); this.calculateMaxLength(); this.heatMapAxis.calculateVisibleLabels(); this.twoDimensional.processDataSource(this.completeAdaptDataSource); this.cellColor.getColorCollection(); this.calculateBounds(); }; /** * To process datasource property. * * @private */ HeatMap.prototype.processInitData = function () { if (this.adaptorModule) { this.adaptorModule.constructDatasource(this.dataSource, this.dataSourceSettings); } else { this.completeAdaptDataSource = this.dataSource; } }; /** * To set render mode of heatmap as SVG or Canvas. * * @private */ HeatMap.prototype.setRenderMode = function () { if (this.renderingMode === 'Canvas') { this.enableCanvasRendering = true; } else if (this.renderingMode === 'Auto' && (this.axisCollections[0].axisLabelSize * this.axisCollections[1].axisLabelSize) >= 10000) { this.enableCanvasRendering = true; } else { this.enableCanvasRendering = false; } }; /** * To set bubble helper private property. * * @private */ HeatMap.prototype.updateBubbleHelperProperty = function () { if (isNullOrUndefined(this.legendModule) || (this.cellSettings.tileType === 'Bubble' && (this.cellSettings.bubbleType === 'Size' || this.cellSettings.bubbleType === 'Sector'))) { this.legendVisibilityByCellType = false; } else if (this.legendModule && this.legendSettings.visible) { this.legendVisibilityByCellType = true; } if (this.cellSettings.tileType === 'Bubble' && this.cellSettings.bubbleType === 'SizeAndColor') { this.bubbleSizeWithColor = true; } else { this.bubbleSizeWithColor = false; } }; HeatMap.prototype.renderElements = function () { this.tooltipCollection = []; this.renderSecondaryElement(); this.renderBorder(); this.renderTitle(); this.heatMapAxis.renderAxes(); if (this.tooltipModule && this.showTooltip) { this.tooltipModule.tooltipObject = null; this.tooltipModule.createTooltipDiv(this); } this.heatMapSeries.renderRectSeries(); if (this.legendModule && this.legendSettings.visible && this.legendVisibilityByCellType) { this.legendModule.renderLegendItems(); if (this.paletteSettings.type === 'Fixed' && this.legendSettings.enableSmartLegend && this.legendSettings.labelDisplayType === 'None') { this.legendModule.createTooltipDiv(); } } removeMeasureElement(); }; /** * Get component name * * @private */ HeatMap.prototype.getModuleName = function () { return 'heatmap'; }; /** * Get the properties to be maintained in the persisted state. * * @private */ HeatMap.prototype.getPersistData = function () { return ''; }; /** * @private */ // tslint:disable-next-line:max-func-body-length HeatMap.prototype.onPropertyChanged = function (newProp, oldProp) { var renderer = false; var refreshBounds = false; var isUpdateSelection = true; for (var _i = 0, _a = Object.keys(newProp); _i < _a.length; _i++) { var prop = _a[_i]; switch (prop) { case 'renderingMode': this.rendering = false; isUpdateSelection = false; renderer = true; break; case 'cellSettings': this.updateBubbleHelperProperty(); if (this.legendModule && ((newProp.cellSettings.tileType !== (oldProp.cellSettings !== undefined && oldProp.cellSettings.tileType)) || (newProp.cellSettings.bubbleType !== oldProp.cellSettings.bubbleType))) { this.legendOnLoad = true; this.legendModule.updateLegendRangeCollections(); } if (this.cellSettings.tileType === 'Bubble') { isUpdateSelection = false; } this.reRenderDatasource(); refreshBounds = true; break; case 'showTooltip': refreshBounds = true; break; case 'dataSource': case 'dataSourceSettings': this.isCellData = false; this.paletteCellSelectionUpdation(); this.reRenderDatasource(); isUpdateSelection = false; renderer = true; break; case 'titleSettings': case 'width': case 'height': case 'margin': case 'backgroundColor': refreshBounds = true; break; case 'legendSettings': this.updateBubbleHelperProperty(); if (this.legendModule && this.legendVisibilityByCellType && (((newProp.legendSettings.visible !== (oldProp.legendSettings !== undefined && oldProp.legendSettings.visible)) || (newProp.legendSettings.enableSmartLegend !== oldProp.legendSettings.enableSmartLegend)))) { this.legendOnLoad = true; this.legendModule.updateLegendRangeCollections(); } else { this.legendOnLoad = false; } refreshBounds = true; break; case 'yAxis': case 'xAxis': this.paletteCellSelectionUpdation(); this.reRenderDatasource(); isUpdateSelection = false; refreshBounds = true; break; case 'paletteSettings': this.paletteCellSelectionUpdation(); this.twoDimensional.processDataSource(this.completeAdaptDataSource); this.cellColor.getColorCollection(); this.calculateBounds(); renderer = true; break; case 'theme': this.setTheme(); renderer = true; break; case 'tooltipSettings': if (this.tooltipModule) { this.tooltipModule.tooltipObject.fill = this.tooltipSettings.fill; this.tooltipModule.tooltipObject.border = this.tooltipSettings.border; this.tooltipModule.tooltipObject.textStyle = this.tooltipSettings.textStyle; this.tooltipModule.tooltipObject.template = this.tooltipSettings.template; this.tooltipModule.tooltipObject.refresh(); } break; } } if (!refreshBounds && renderer) { this.createSvg(); this.renderElements(); this.appendSvgObject(); this.trigger('created'); if (!isUpdateSelection) { this.clearSelection(); } } else if (refreshBounds) { this.createSvg(); this.refreshBound(); this.appendSvgObject(); this.trigger('created'); } if (this.allowSelection && this.rectSelected) { if (isUpdateSelection) { this.updateCellSelection(); } else { this.clearSelection(); } } this.rendering = true; }; HeatMap.prototype.paletteCellSelectionUpdation = function () { this.updateBubbleHelperProperty(); if (this.legendModule && this.legendVisibilityByCellType) { this.legendOnLoad = true; this.legendModule.updateLegendRangeCollections(); } }; /** * create svg or canvas element * * @private */ HeatMap.prototype.createSvg = function () { this.removeSvg(); this.setRenderMode(); this.calculateSize(); if (!this.enableCanvasRendering) { this.svgObject = this.renderer.createSvg({ id: this.element.id + '_svg', width: this.availableSize.width, height: this.availableSize.height }); if (this.cellSettings.border.width.toString() === '0' && this.cellSettings.tileType === 'Rect') { this.svgObject.setAttribute('shape-rendering', 'crispEdges'); } } else { this.svgObject = this.canvasRenderer.createCanvas({ id: this.element.id + '_canvas', width: this.availableSize.width, height: this.availableSize.height }); if (this.allowSelection) { this.createMultiCellDiv(true); } } }; /** * To Remove the SVG. * * @private */ HeatMap.prototype.removeSvg = function () { if (document.getElementById(this.element.id + '_Secondary_Element')) { remove(document.getElementById(this.element.id + '_Secondary_Element')); } if (document.getElementById(this.element.id + 'Celltooltipcontainer')) { remove(document.getElementById(this.element.id + 'Celltooltipcontainer')); } if (document.getElementById(this.element.id + 'legendLabelTooltipContainer')) { remove(document.getElementById(this.element.id + 'legendLabelTooltipContainer')); } if (document.getElementById(this.element.id + '_Multi_CellSelection_Canvas')) { remove(document.getElementById(this.element.id + '_Multi_CellSelection_Canvas')); } if (document.getElementById(this.element.id + '_CellSelection_Container')) { remove(document.getElementById(this.element.id + '_CellSelection_Container')); } if (document.getElementById(this.element.id + '_secondary_canvas')) { remove(document.getElementById(this.element.id + '_secondary_canvas')); } if (this.svgObject) { var svgElement = document.getElementById(this.svgObject.id); if (svgElement) { while (this.svgObject.childNodes.length) { this.svgObject.removeChild(this.svgObject.firstChild); } remove(this.svgObject); } } }; HeatMap.prototype.renderSecondaryElement = function () { var tooltipDiv = this.createElement('div'); tooltipDiv.id = this.element.id + '_Secondary_Element'; this.element.appendChild(tooltipDiv); var divElement = this.createElement('div', { id: this.element.id + '_CellSelection_Container' }); divElement.style.cssText = 'position:absolute; z-index: 2 ; top:' + this.initialClipRect.y + 'px' + '; left:' + this.initialClipRect.x + 'px'; this.element.appendChild(divElement); }; /** * To provide the array of modules needed for control rendering * * @returns {ModuleDeclaration[]} * @private */ HeatMap.prototype.requiredModules = function () { var modules = []; if (this.showTooltip) { modules.push({ member: 'Tooltip', args: [this], name: 'Tooltip' }); } if (this.legendSettings.visible) { modules.push({ member: 'Legend', args: [this], name: 'Legend' }); } if (!isNullOrUndefined(this.dataSourceSettings) && ((this.dataSourceSettings.adaptorType === 'Table' && this.dataSourceSettings.isJsonData) || this.dataSourceSettings.adaptorType === 'Cell')) { modules.push({ member: 'Adaptor', args: [this], name: 'Adaptor' }); } return modules; }; /** * This method destroys the heatmap. This method removes the events associated with the heatmap and disposes the objects created for rendering and updating the heatmap. * {% codeBlock src='heatmap/destroy/index.md' %}{% endcodeBlock %} * * @function destroy * @returns {void}. * @member of Heatmap */ HeatMap.prototype.destroy = function () { this.unWireEvents(); this.touchInstance.destroy(); this.touchInstance = null; for (var i = 0; i < this.axisCollections.length; i++) { this.axisCollections[i].destroy(); } this.axisCollections = null; if (!isNullOrUndefined(this.heatMapSeries)) { this.heatMapSeries.destroy(); } this.heatMapSeries = null; if (!isNullOrUndefined(this.heatMapAxis)) { this.heatMapAxis.destroy(); } this.heatMapAxis = null; _super.prototype.destroy.call(this); removeMeasureElement(); if (!isNullOrUndefined(this.twoDimensional)) { this.twoDimensional.destroy(); } this.twoDimensional = null; this.element.innerHTML = ''; this.availableSize = null; this.elementSize = null; this.initialClipRect = null; this.element.classList.remove('e-heatmap'); this.drawSvgCanvas = null; this.cellColor = null; this.colorCollection = null; this.legendColorCollection = null; this.clonedDataSource = null; this.completeAdaptDataSource = null; this.currentRect = null; this.dataMax = null; this.dataMin = null; this.previousRect = null; this.selectedCellsRect = null; this.canvasSelectedCells = null; this.titleRect = null; this.tooltipCollection = null; this.border = null; this.intl = null; this.titleCollection = null; this.themeStyle = null; this.renderer = null; this.canvasRenderer = null; this.secondaryCanvasRenderer = null; this.svgObject = null; this.resizeEvent = null; this.toggleValue = []; this.previousSelectedCellsRect = []; this.selectedMultiCellCollection = []; this.tempMultiCellCollection = []; }; /** * Applies all the pending property changes and render the component again. * * @function destroy * @returns {void}. */ HeatMap.prototype.refresh = function () { _super.prototype.refresh.call(this); this.element.classList.add('e-heatmap'); }; /** * Appending svg object to the element * * @private */ HeatMap.prototype.appendSvgObject = function () { this.element.appendChild(this.svgObject); if (this.enableCanvasRendering && this.allowSelection) { this.createMultiCellDiv(false); } }; HeatMap.prototype.renderBorder = function () { this.border = { width: 0 }; var background = !isNullOrUndefined(this.backgroundColor) ? this.backgroundColor : this.themeStyle.background; var width = 0; var rect = new RectOption(this.element.id + '_HeatmapBorder', background, this.border, 1, new Rect(width / 2, width / 2, this.availableSize.width - width, this.availableSize.height - width)); this.drawSvgCanvas.drawRectangle(rect, this.svgObject); }; HeatMap.prototype.calculateSize = function () { var width = stringToNumber(this.width, this.element.offsetWidth) || this.element.offsetWidth || 600; var height = stringToNumber(this.height, this.element.offsetHeight) || this.element.offsetHeight || 450; this.availableSize = new Size(width, height); var alignElement = this.element; while (alignElement.parentNode) { if (alignElement.tagName === 'BODY') { break; } var align = alignElement.align; if (align === 'center') { var containerWidth = this.availableSize.width.toString(); this.element.style.width = containerWidth + 'px'; this.element.style.margin = '0 auto'; break; } alignElement = alignElement.parentElement; } }; HeatMap.prototype.renderTitle = function () { if (this.titleSettings.text) { var titleStyle = this.titleSettings.textStyle; var anchor = titleStyle.textAlignment === 'Near' ? 'start' : titleStyle.textAlignment === 'Far' ? 'end' : 'middle'; this.elementSize = measureText(this.titleCollection[0], titleStyle); var options = new TextOption(this.element.id + '_HeatmapTitle', new TextBasic(titlePositionX(this.availableSize.width - this.margin.left - this.margin.right, this.margin.left, this.margin.right, titleStyle), this.margin.top + ((this.elementSize.height) * 3 / 4), anchor, this.titleCollection), titleStyle, titleStyle.color || this.themeStyle.heatMapTitle); if (this.titleCollection.length > 1) { this.drawSvgCanvas.createWrapText(options, titleStyle, this.svgObject); } else { this.drawSvgCanvas.createText(options, this.svgObject, this.titleCollection[0]); if (this.titleCollection[0].indexOf('...') !== -1 && this.enableCanvasRendering) { this.tooltipCollection.push(new CanvasTooltip(this.titleSettings.text, new Rect(this.margin.left, this.margin.top, this.elementSize.width, this.elementSize.height))); } } } }; HeatMap.prototype.titleTooltip = function (event, x, y, isTouch) { var targetId = event.target.id; if ((targetId === (this.element.id + '_HeatmapTitle')) && (event.target.textContent.indexOf('...') > -1)) { showTooltip(this.titleSettings.text, x, y, this.element.offsetWidth, this.element.id + '_Title_Tooltip', getElement(this.element.id + '_Secondary_Element'), isTouch, this); } else { removeElement(this.element.id + '_Title_Tooltip'); } }; // eslint-disable-next-line HeatMap.prototype.axisTooltip = function (event, x, y, isTouch) { var targetId = event.target.id; if ((targetId.indexOf(this.element.id + '_XAxis_Label') !== -1) || (targetId.indexOf(this.element.id + '_YAxis_Label') !== -1) || (targetId.indexOf(this.element.id + '_XAxis_MultiLevel') !== -1) || (targetId.indexOf(this.element.id + '_YAxis_MultiLevel') !== -1)) { var tooltipText = getTooltipText(this.tooltipCollection, x, y); if (tooltipText) { showTooltip(tooltipText, x, y, this.element.offsetWidth, this.element.id + '_axis_Tooltip', getElement(this.element.id + '_Secondary_Element'), this.isTouch, this); } else { removeElement(this.element.id + '_axis_Tooltip'); } } else { removeElement(this.element.id + '_axis_Tooltip'); } }; HeatMap.prototype.isHeatmapRect = function (x, y) { var firstRectDetails = []; var lastRectDetails = []; var isRect; var borderBoundary = 5; if (this.heatMapSeries.rectPositionCollection.length > 0) { firstRectDetails.push(this.heatMapSeries.rectPositionCollection[0][0]); lastRectDetails.push(this.heatMapSeries.rectPositionCollection[this.yLength - 1][this.xLength - 1]); } if (firstRectDetails.length > 0 && lastRectDetails.length > 0) { if (this.cellSettings.border.width > borderBoundary && (x >= firstRectDetails[0].x && y >= firstRectDetails[0].y && x <= (lastRectDetails[0].x + lastRectDetails[0].width) && y <= (lastRectDetails[0].y + lastRectDetails[0].height)) && this.cellSettings.tileType === 'Rect') { var currentRect = this.heatMapSeries.getCurrentRect(x, y); var rectHeight = lastRectDetails[0].height; var rectWidth = lastRectDetails[0].width; var cellBorder = this.cellSettings.border.width / 2; if ((x >= (currentRect.x + cellBorder) && (y >= (currentRect.y + cellBorder)) && (x <= (currentRect.x + (rectWidth - cellBorder)) && (y <= (currentRect.y + (rectHeight - cellBorder)))))) { isRect = true; this.isRectBoundary = true; } else { isRect = false; this.isRectBoundary = false; } } else { isRect = (x >= firstRectDetails[0].x && y >= firstRectDetails[0].y && x <= (lastRectDetails[0].x + lastRectDetails[0].width) && y <= (lastRectDetails[0].y + lastRectDetails[0].height)); this.isRectBoundary = isRect; } } return isRect; }; HeatMap.prototype.setTheme = function () { /*! Set theme */ this.themeStyle = getThemeColor(this.theme); }; HeatMap.prototype.calculateBounds = function () { var margin = this.margin; // Title Height; var titleHeight = 0; var padding = (this.legendModule && this.legendSettings.position === 'Top' && this.legendVisibilityByCellType) || this.titleSettings.textStyle.size === '0px' ? 0 : 16; // title padding var left = margin.left; var width = this.availableSize.width - left - margin.right; if ((this.paletteSettings.colorGradientMode === 'Column' || this.paletteSettings.colorGradientMode === 'Row') && this.paletteSettings.type === 'Gradient') { if (this.paletteSettings.palette.length === 0) { this.legendVisibilityByCellType = false; } else { for (var i = 0; i < this.paletteSettings.palette.length; i++) { if (this.paletteSettings.palette[i].value !== null || '') { this.legendVisibilityByCellType = true; } else if (this.paletteSettings.palette[i].value === null || '') { this.legendVisibilityByCellType = false; break; } } } } if (this.titleSettings.text) { var titleText = this.enableHtmlSanitizer ? SanitizeHtmlHelper.sanitize(this.titleSettings.text) : this.titleSettings.text; this.titleCollection = getTitle(titleText, this.titleSettings.textStyle, width); titleHeight = (measureText(titleText, this.titleSettings.textStyle).height * this.titleCollection.length) + padding; } var top = margin.top + titleHeight; this.titleRect = new Rect(margin.left, margin.top, this.availableSize.width - margin.left - margin.right, titleHeight); var height = this.availableSize.height - top - margin.bottom; this.initialClipRect = new Rect(left, top, width, height); var legendTop = this.initialClipRect.y; if (this.legendModule && this.legendSettings.visible && this.legendVisibilityByCellType) { this.legendModule.calculateLegendBounds(this.initialClipRect); } this.heatMapAxis.measureAxis(this.initialClipRect); if (this.legendModule && this.legendSettings.visible && this.legendVisibilityByCellType) { this.legendModule.calculateLegendSize(this.initialClipRect, legendTop); } this.heatMapAxis.calculateAxisSize(this.initialClipRect); }; HeatMap.prototype.refreshBound = function () { this.updateBubbleHelperProperty(); this.calculateBounds(); this.renderElements(); }; HeatMap.prototype.initAxis = function () { var axis; var axes = [this.xAxis, this.yAxis]; this.axisCollections = []; for (var i = 0, len = axes.length; i < len; i++) { axis = axes[i]; axis.orientation = (i === 0) ? 'Horizontal' : 'Vertical'; axis.jsonCellLabel = []; this.axisCollections.push(axis); } }; /** * Method to bind events for HeatMap */ HeatMap.prototype.wireEvents = function () { var _this = this; /*! Find the Events type */ // eslint-disable-next-line var isIE11Pointer = Browser.isPointer; var start = Browser.touchStartEvent; var stop = Browser.touchEndEvent; var move = Browser.touchMoveEvent; var cancel = isIE11Pointer ? 'pointerleave' : 'mouseleave'; EventHandler.add(this.element, Browser.isDevice ? start : 'click', this.heatMapMouseClick, this); EventHandler.add(this.element, 'contextmenu', this.heatMapMouseRightClick, this); EventHandler.add(this.element, 'dblclick', this.heatMapMouseDoubleClick, this); EventHandler.add(this.element, start, this.heatMapMouseMove, this); EventHandler.add(this.element, stop, this.heatMapMouseLeave, this); EventHandler.add(this.element, move, this.heatMapMouseMove, this); EventHandler.add(this.element, cancel, this.heatMapMouseLeave, this); EventHandler.add(this.element, 'keyup', this.heatMapKeyUp, this); EventHandler.add(this.element, 'keydown', this.heatMapKeyDown, this); this.resizeEvent = this.heatMapResize.bind(this); window.addEventListener((Browser.isTouch && ('orientation' in window && 'onorientationchange' in window)) ? 'orientationchange' : 'resize', this.resizeEvent); // eslint-disable-next-line var heatmap = this; /** * Support for touch tapHold and tap for HeatMap */ this.touchInstance = new Touch(this.element, { tapHold: function (e) { var targetId = e.originalEvent.target.id; if ((targetId.indexOf(_this.element.id + '_HeatMapRect_') !== -1 || targetId.indexOf(_this.element.id + '_HeatMapRectLabels_') !== -1) && _this.allowSelection) { heatmap.isCellTapHold = true; var selectedCellCollection = []; for (var i = 0; i < _this.multiCellCollection.length; i++) { selectedCellCollection.push(_this.multiCellCollection[i]); } if (!e.originalEvent.ctrlKey || !_this.enableMultiSelect) { _this.multiCellCollection = []; } heatmap.getDataCollection(); var argData = { heatmap: heatmap, cancel: false, name: 'cellSelected', data: heatmap.multiCellCollection }; heatmap.trigger('cellSelected', argData); if (!argData.cancel) { // eslint-disable-next-line @typescript-eslint/no-explicit-any if (e.ctrlKey === false || !_this.enableMultiSelect) { _this.removeSelectedCellsBorder(false); } heatmap.currentRect.allowCollection = false; } else { _this.multiCellCollection = selectedCellCollection; // eslint-disable-next-line @typescript-eslint/no-explicit-any if (_this.multiCellCollection.length > 0 || e.ctrlKey === false || !_this.enableMultiSelect) { _this.removeSelectedCellsBorder(true); } } heatmap.setCellOpacity(); window.clearTimeout(_this.tooltipTimer); heatmap.tooltipOnMouseMove(null, heatmap.currentRect, heatmap.isCellTapHold); } }, // eslint-disable-next-line @typescript-eslint/tslint/config tap: function (e) { var targetId = e.originalEvent.target.id; if ((targetId.indexOf(_this.element.id + '_HeatMapRect_') !== -1 || targetId.indexOf(_this.element.id + '_HeatMapRectLabels_') !== -1 || targetId.indexOf(_this.element.id + '_CellSelection_Container_') !== -1)) { var isCellTap = false; if (!heatmap.isCellTapHold) { isCellTap = true; } var pageX = void 0; var pageY = void 0; var touchArg = void 0; var elementRect = _this.element.getBoundingClientRect(); if (e.originalEvent.type === 'touchend' || e.originalEvent.type === 'touchstart') { _this.isTouch = true; touchArg = e.originalEvent; pageX = touchArg.changedTouches[0].clientX; pageY = touchArg.changedTouches[0].clientY; } else { _this.isTouch = false; pageX = e.originalEvent.clientX; pageY = e.originalEvent.clientY; } pageX -= elementRect.left; pageY -= elementRect.top; var currentRect = _this.heatMapSeries.getCurrentRect(pageX, pageY); window.clearTimeout(_this.tooltipTimer); heatmap.tooltipOnMouseMove(null, currentRect, isCellTap); } } }); this.setStyle(this.element); }; /** * Applying styles for heatmap element */ HeatMap.prototype.setStyle = function (element) { element.style.touchAction = 'element'; element.style.touchAction = 'element'; element.style.zoom = 'none'; element.style.userSelect = 'none'; element.style.webkitUserSelect = 'none'; element.style.position = 'relative'; element.style.display = 'block'; element.style.overflow = 'hidden'; }; /** * This method is used to print the rendered heatmap. */ HeatMap.prototype.print = function () { var exportChart = new ExportUtils(this); exportChart.print(); }; /** * Method to unbind events for HeatMap */ HeatMap.prototype.unWireEvents = function () { /*! Find the Events type */ // eslint-disable-next-line var isIE11Pointer = Browser.isPointer; var start = Browser.touchStartEvent; var stop = Browser.touchEndEvent; var move = Browser.touchMoveEvent; var cancel = isIE11Pointer ? 'pointerleave' : 'mouseleave'; EventHandler.remove(this.element, Browser.isDevice ? start : 'click', this.heatMapMouseClick); EventHandler.remove(this.element, 'contextmenu', this.heatMapMouseRightClick); EventHandler.remove(this.element, 'dblclick', this.heatMapMouseDoubleClick); EventHandler.remove(this.element, start, this.heatMapMouseMove); EventHandler.remove(this.element, stop, this.heatMapMouseLeave); EventHandler.remove(this.element, move, this.heatMapMouseMove); EventHandler.remove(this.element, cancel, this.heatMapMouseLeave); EventHandler.remove(this.element, 'keyup', this.heatMapKeyUp); EventHandler.remove(this.element, 'keydown', this.heatMapKeyDown); window.removeEventListener((Browser.isTouch && ('orientation' in window && 'onorientationchange' in window)) ? 'orientationchange' : 'resize', this.resizeEvent); }; /** * Handles the heatmap resize. * * @returns {boolean} * @private */ // eslint-disable-next-line HeatMap.prototype.heatMapResize = function (e) { var _this = this; this.resizing = true; var argData = { heatmap: this, cancel: false, name: 'resized', currentSize: new Size(0, 0), previousSize: new Size(this.availableSize.width, this.availableSize.height) }; if (this.resizeTimer) { clearTimeout(this.resizeTimer); } this.resizeTimer = setTimeout(function () { if (_this.isDestroyed) { clearTimeout(_this.resizeTimer); return; } _this.createSvg(); argData.currentSize = _this.availableSize; _this.trigger('resized', argData); _this.refreshBound(); _this.appendSvgObject(); if (_this.allowSelection) { _this.updateCellSelection(); } _this.trigger('loaded', ({ heatmap: _this })); _this.resizing = false; }, 500); return false; }; /** * Method to bind selection after window resize for HeatMap */ HeatMap.prototype.updateCellSelection = function () { var wSize = this.initialClipRect.width / this.axisCollections[0].axisLabelSize; var hSize = this.initialClipRect.height / this.axisCollections[1].axisLabelSize; var x = this.initialClipRect.x; var y = this.initialClipRect.y; if (!this.enableCanvasRendering) { if (this.multiCellCollection.length !== 0) { var containersRect = document.getElementById(this.element.id + '_Container_RectGroup'); var containerText = document.getElementById(this.element.id + '_Container_TextGroup'); for (var i = 0; i < containersRect.childNodes.length; i++) { containersRect.childNodes[i].setAttribute('opacity', '0.3'); if (this.cellSettings.showLabel && containerText.childNodes[i]) { containerText.childNodes[i].setAttribute('opacity', '0.3'); } } for (var i = 0; i < this.multiCellCollection.length; i++) { var collectionClass = this.multiCellCollection[i].cellElement; var cellIndex = collectionClass.id.replace(this.element.id + '_HeatMapRect_', ''); var index = parseInt(cellIndex, 10); containersRect.childNodes[index].setAttribute('opacity', '1'); if (this.cellSettings.showLabel && containerText.childNodes[i]) { var getText = document.getElementById(this.element.id + '_HeatMapRectLabels_' + index); if (getText) { getText.setAttribute('opacity', '1'); } this.addSvgClass(containersRect.childNodes[index]); } } } } else if (this.enableCanvasRendering) { var rect = this.multiCellCollection; var oldCanvas = document.getElementById(this.element.id + '_canvas'); var newCanvas = document.getElementById(this.element.id + '_secondary_canvas'); var initialRect = this.initialClipRect; var rectHeight = initialRect.y + initialRect.height; var rectWidth = initialRect.x + initialRect.width; for (var i = 0; i < this.multiCellCollection.length; i++) { this.multiCellCollection[i].width = rect[i].width = wSize; this.multiCellCollection[i].height = rect[i].height = hSize; this.multiCellCollection[i].x = rect[i].x = x + wSize * this.multiCellCollection[i].xPosition; this.multiCellCollection[i].y = rect[i].y = y + hSize * this.multiCellCollection[i].yPosition; var rectImage = oldCanvas.getContext('2d').getImageData(rect[i].x, rect[i].y, rect[i].width, rect[i].height); newCanvas.getContext('2d').putImageData(rectImage, rect[i].x, rect[i].y); oldCanvas.style.opacity = '0.3'; } var topPositions = oldCanvas.getContext('2d').getImageData(0, 0, this.availableSize.width, initialRect.y); newCanvas.getContext('2d').putImageData(topPositions, 0, 0); var bottomPositions = oldCanvas.getContext('2d').getImageData(0, rectHeight, this.availableSize.width, this.availableSize.height - rectHeight); newCanvas.getContext('2d').putImageData(bottomPositions, 0, initialRect.y + initialRect.height); var rightPosition = oldCanvas.getContext('2d'). getImageData(rectWidth, 0, this.availableSize.width - rectWidth, this.availableSize.height); newCanvas.getContext('2d').putImageData(rightPosition, rectWidth, 0); var leftPosition = oldCanvas.getContext('2d').getImageData(0, 0, initialRect.x, this.availableSize.height); newCanvas.getContext('2d').putImageData(leftPosition, 0, 0); removeElement(this.element.id + '_selectedCells'); } }; HeatMap.prototype.clearS