@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
JavaScript
/**
* 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