@syncfusion/ej2-heatmap
Version:
Feature rich data visulization control used to visualize the matrix data where the individual values are represented as colors
1,372 lines (1,368 loc) • 461 kB
JavaScript
import { ChildProperty, Property, Complex, Collection, isNullOrUndefined, extend, createElement, SanitizeHtmlHelper, compile, remove, Browser, merge, select, print, Component, Internationalization, EventHandler, Touch, Event, NotifyPropertyChanges } from '@syncfusion/ej2-base';
import { SvgRenderer, Tooltip as Tooltip$1, CanvasRenderer } from '@syncfusion/ej2-svg-base';
import { DataUtil } from '@syncfusion/ej2-data';
import { PdfPageOrientation, PdfDocument, SizeF, PdfBitmap } from '@syncfusion/ej2-pdf-export';
/**
* Specifies HeatMaps Themes
*/
// eslint-disable-next-line @typescript-eslint/no-namespace
var Theme;
(function (Theme) {
/** @private */
Theme.heatMapTitleFont = {
size: '15px',
fontWeight: '500',
color: null,
fontStyle: 'Normal',
fontFamily: 'Segoe UI'
};
/** @private */
Theme.titleFont = {
size: '13px',
fontWeight: 'Normal',
color: null,
fontStyle: 'Normal',
fontFamily: 'Segoe UI',
textOverflow: 'None'
};
/** @private */
Theme.axisTitleFont = {
size: '12px',
fontWeight: 'Normal',
color: null,
fontStyle: 'Normal',
fontFamily: 'Segoe UI'
};
/** @private */
Theme.axisLabelFont = {
size: '12px',
fontWeight: 'Normal',
color: null,
fontStyle: 'Normal',
fontFamily: 'Segoe UI',
textOverflow: 'None'
};
/** @private */
Theme.legendLabelFont = {
size: '12px',
fontWeight: 'Normal',
color: null,
fontStyle: 'Normal',
fontFamily: 'Segoe UI',
textOverflow: 'None'
};
/** @private */
Theme.rectLabelFont = {
size: '12px',
fontWeight: 'Normal',
color: null,
fontStyle: 'Normal',
fontFamily: 'Segoe UI',
textOverflow: 'None'
};
/** @private */
Theme.tooltipFont = {
size: '13px',
fontWeight: 'Normal',
color: null,
fontStyle: 'Normal',
fontFamily: 'Segoe UI',
textOverflow: 'None'
};
})(Theme || (Theme = {}));
/**
* Functions to check whether target object implement specific interface.
*
* @param { HeatMapTheme } theme - specifies the value.
* @returns { IThemeStyle } returns the theme style
* @private
*/
function getThemeColor(theme) {
let style;
switch (theme.toLowerCase()) {
case 'highcontrastlight':
case 'highcontrast':
style = {
heatMapTitle: '#ffffff',
axisTitle: '#ffffff',
axisLabel: '#ffffff',
cellBorder: '#EEEEEE',
background: '#000000',
cellTextColor: '#000000',
toggledColor: '#000000',
emptyCellColor: '#EEEEEE',
legendLabel: '#ffffff',
palette: [{ 'color': '#BEE7EE' },
{ 'color': '#85c4cf' },
{ 'color': '#4CA1AF' }]
};
break;
case 'materialdark':
case 'fabricdark':
case 'bootstrapdark':
style = {
heatMapTitle: '#ffffff',
axisTitle: '#ffffff',
axisLabel: '#DADADA',
cellBorder: '#EEEEEE',
background: '#000000',
cellTextColor: '#000000',
toggledColor: '#000000',
emptyCellColor: '#EEEEEE',
legendLabel: '#ffffff',
palette: [{ 'color': '#BEE7EE' },
{ 'color': '#85c4cf' },
{ 'color': '#4CA1AF' }]
};
break;
case 'bootstrap4':
style = {
heatMapTitle: '#212529',
axisTitle: '#212529',
axisLabel: '#212529',
cellBorder: '#E9ECEF',
background: '#FFFFFF',
cellTextColor: '#212529',
toggledColor: '#ffffff',
emptyCellColor: '#E9ECEF',
legendLabel: '#212529',
palette: [{ 'color': '#BEE7EE' },
{ 'color': '#85c4cf' },
{ 'color': '#4CA1AF' }]
};
break;
case 'tailwind':
style = {
heatMapTitle: '#374151',
axisTitle: '#374151',
axisLabel: '#6B7280',
cellBorder: '#E5E7EB',
background: 'transparent',
cellTextColor: '#111827',
toggledColor: 'transparent',
emptyCellColor: '#E5E7EB',
legendLabel: '#374151',
palette: [{ 'color': '#5A61F6' },
{ 'color': '#65A30D' },
{ 'color': '#14B8A6' }]
};
break;
case 'tailwinddark':
style = {
heatMapTitle: '#D1D5DB',
axisTitle: '#D1D5DB',
axisLabel: '#9CA3AF',
cellBorder: '#4B5563',
background: 'transparent',
cellTextColor: '#FFFFFF',
toggledColor: 'transparent',
emptyCellColor: '#374151',
legendLabel: '#D1D5DB',
palette: [{ 'color': '#8B5CF6' },
{ 'color': '#22D3EE' },
{ 'color': '#F87171' }]
};
break;
case 'tailwind3':
style = {
heatMapTitle: '#111827',
axisTitle: '#111827',
axisLabel: '#4B5563',
cellBorder: '#E5E7EB',
background: 'transparent',
cellTextColor: '#111827',
toggledColor: 'transparent',
emptyCellColor: '#E5E7EB',
legendLabel: '#4B5563',
palette: [{ 'color': '#2F4074' },
{ 'color': '#03B4B4' },
{ 'color': '#0D72DE' }]
};
break;
case 'tailwind3dark':
style = {
heatMapTitle: '#FFFFFF',
axisTitle: '#FFFFFF',
axisLabel: '#D1D5DB',
cellBorder: '#282F3C',
background: 'transparent',
cellTextColor: '#FFFFFF',
toggledColor: 'transparent',
emptyCellColor: '#282F3C',
legendLabel: '#D1D5DB',
palette: [{ 'color': '#8029F1' },
{ 'color': '#1ABC9C' },
{ 'color': '#0D72DE' }]
};
break;
case 'bootstrap5':
style = {
heatMapTitle: '#212529',
axisTitle: '#212529',
axisLabel: '#212529',
cellBorder: 'transparent',
background: 'transparent',
toggledColor: '#E9ECEF',
emptyCellColor: '#E9ECEF',
legendLabel: '#212529',
palette: [{ 'color': '#DC3545' },
{ 'color': '#FFC107' },
{ 'color': '#D63384' }]
};
break;
case 'bootstrap5dark':
style = {
heatMapTitle: '#DEE2E6',
axisTitle: '#DEE2E6',
axisLabel: '#DEE2E6',
cellBorder: 'transparent',
background: 'transparent',
toggledColor: '#343A40',
emptyCellColor: '#343A40',
legendLabel: '#DEE2E6',
palette: [{ 'color': '#DC3545' },
{ 'color': '#FFC107' },
{ 'color': '#D63384' }]
};
break;
case 'fluent':
style = {
heatMapTitle: '#201F1E',
axisTitle: '#201F1E',
axisLabel: '#201F1E',
cellBorder: '#EDEBE9',
background: 'transparent',
cellTextColor: '#111827',
toggledColor: 'transparent',
emptyCellColor: '#EDEBE9',
legendLabel: '#201F1E',
palette: [{ 'color': '#EDEBE9' },
{ 'color': '#614570' },
{ 'color': '#4C6FB1' }]
};
break;
case 'fluentdark':
style = {
heatMapTitle: '#F3F2F1',
axisTitle: '#F3F2F1',
axisLabel: '#F3F2F1',
cellBorder: '#EDEBE9',
background: 'transparent',
cellTextColor: '#FFFFFF',
toggledColor: 'transparent',
emptyCellColor: '#292827',
legendLabel: '#F3F2F1',
palette: [{ 'color': '#292827' },
{ 'color': '#2A72D5' },
{ 'color': '#43B786' }]
};
break;
case 'material3':
style = {
heatMapTitle: '#1C1B1F',
axisTitle: '#1C1B1F',
axisLabel: '#1C1B1F',
cellBorder: '#C4C7C5',
background: 'transparent',
cellTextColor: '#1C1B1F',
toggledColor: '#F6F0FB',
emptyCellColor: '#F6F0FB',
legendLabel: '#49454E',
palette: [{ 'color': '#6200EE' },
{ 'color': '#E77A16' },
{ 'color': '#82C100' }]
};
break;
case 'material3dark':
style = {
heatMapTitle: '#E6E1E5',
axisTitle: '#E6E1E5',
axisLabel: '#E6E1E5',
cellBorder: '#444746',
background: 'transparent',
cellTextColor: '#E6E1E5',
toggledColor: '#49454F',
emptyCellColor: '#49454E',
legendLabel: '#CAC4D0',
palette: [{ 'color': '#4EAAFF' },
{ 'color': '#FA4EAB' },
{ 'color': '#FFF500' }]
};
break;
case 'fluent2':
style = {
heatMapTitle: '#242424',
axisTitle: '#242424',
axisLabel: '#242424',
cellBorder: 'transparent',
background: 'transparent',
cellTextColor: '#242424',
toggledColor: '#EDEBE9',
emptyCellColor: '#EDEBE9',
legendLabel: '#242424',
palette: [{ 'color': '#6200EE' },
{ 'color': '#09AF74' },
{ 'color': '#0076E5' }]
};
break;
case 'fluent2dark':
case 'fluent2highcontrast':
style = {
heatMapTitle: '#FFFFFF',
axisTitle: '#FFFFFF',
axisLabel: '#FFFFFF',
cellBorder: 'transparent',
background: 'transparent',
cellTextColor: '#FFFFFF',
toggledColor: '#292827',
emptyCellColor: '#292827',
legendLabel: '#FFFFFF',
palette: [{ 'color': '#9BB449' },
{ 'color': '#2A72D5' },
{ 'color': '#43B786' }]
};
break;
default:
style = {
heatMapTitle: '#424242',
axisTitle: '#424242',
axisLabel: '#686868',
cellBorder: '#EEEEEE',
cellTextColor: '#000000',
toggledColor: '#ffffff',
background: '#FFFFFF',
emptyCellColor: '#EEEEEE',
legendLabel: '#353535',
palette: [{ 'color': '#BEE7EE' },
{ 'color': '#85c4cf' },
{ 'color': '#4CA1AF' }]
};
break;
}
return style;
}
var __decorate = (undefined && undefined.__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;
};
/**
* Sets and gets the options to customize the text in heatmap.
*/
class Font extends ChildProperty {
}
__decorate([
Property('16px')
], Font.prototype, "size", void 0);
__decorate([
Property('')
], Font.prototype, "color", void 0);
__decorate([
Property('Segoe UI')
], Font.prototype, "fontFamily", void 0);
__decorate([
Property('Normal')
], Font.prototype, "fontWeight", void 0);
__decorate([
Property('Normal')
], Font.prototype, "fontStyle", void 0);
__decorate([
Property('Center')
], Font.prototype, "textAlignment", void 0);
__decorate([
Property('Trim')
], Font.prototype, "textOverflow", void 0);
/**
* Sets and gets the options to configures the margins of the heatmap.
*/
class Margin extends ChildProperty {
}
__decorate([
Property(10)
], Margin.prototype, "left", void 0);
__decorate([
Property(10)
], Margin.prototype, "right", void 0);
__decorate([
Property(10)
], Margin.prototype, "top", void 0);
__decorate([
Property(10)
], Margin.prototype, "bottom", void 0);
/**
* Sets and gets the options to customize the borders in the heatmap.
*/
class Border extends ChildProperty {
}
__decorate([
Property('')
], Border.prototype, "color", void 0);
__decorate([
Property(1)
], Border.prototype, "width", void 0);
__decorate([
Property('')
], Border.prototype, "radius", void 0);
/**
* Sets and gets the options to customize the tooltip borders in the heatmap.
*/
class TooltipBorder extends ChildProperty {
}
__decorate([
Property('')
], TooltipBorder.prototype, "color", void 0);
__decorate([
Property(0)
], TooltipBorder.prototype, "width", void 0);
/**
* Sets and gets the options to configure the mapping value for size and color in bubble cell type.
*/
class BubbleData extends ChildProperty {
}
__decorate([
Property(null)
], BubbleData.prototype, "size", void 0);
__decorate([
Property(null)
], BubbleData.prototype, "color", void 0);
/**
* Sets and gets the options to customize the title of heatmap.
*/
class Title extends ChildProperty {
}
__decorate([
Property('')
], Title.prototype, "text", void 0);
__decorate([
Complex({}, Font)
], Title.prototype, "textStyle", void 0);
/**
* Sets and gets the options to apply the fill color value for cell color range.
*/
class FillColor extends ChildProperty {
}
__decorate([
Property('#eeeeee')
], FillColor.prototype, "minColor", void 0);
__decorate([
Property('#eeeeee')
], FillColor.prototype, "maxColor", void 0);
/**
* Sets and gets the options to customize palette colors.
*/
class PaletteCollection extends ChildProperty {
}
__decorate([
Property(null)
], PaletteCollection.prototype, "value", void 0);
__decorate([
Property(null)
], PaletteCollection.prototype, "color", void 0);
__decorate([
Property(null)
], PaletteCollection.prototype, "label", void 0);
__decorate([
Property(null)
], PaletteCollection.prototype, "startValue", void 0);
__decorate([
Property(null)
], PaletteCollection.prototype, "endValue", void 0);
__decorate([
Property(null)
], PaletteCollection.prototype, "minColor", void 0);
__decorate([
Property(null)
], PaletteCollection.prototype, "maxColor", void 0);
/**
* Sets and gets the options to customize the label border.
*/
class AxisLabelBorder extends ChildProperty {
}
__decorate([
Property('#b5b5b5')
], AxisLabelBorder.prototype, "color", void 0);
__decorate([
Property(1)
], AxisLabelBorder.prototype, "width", void 0);
__decorate([
Property('Rectangle')
], AxisLabelBorder.prototype, "type", void 0);
/**
* Sets and gets the options to customize the size of the bubble heatmap cell type.
*/
class BubbleSize extends ChildProperty {
}
__decorate([
Property('0%')
], BubbleSize.prototype, "minimum", void 0);
__decorate([
Property('100%')
], BubbleSize.prototype, "maximum", void 0);
/**
* Sets and gets the options to configure the multi-level labels.
*/
class MultiLevelCategories extends ChildProperty {
}
__decorate([
Property(null)
], MultiLevelCategories.prototype, "start", void 0);
__decorate([
Property(null)
], MultiLevelCategories.prototype, "end", void 0);
__decorate([
Property('')
], MultiLevelCategories.prototype, "text", void 0);
__decorate([
Property(null)
], MultiLevelCategories.prototype, "maximumTextWidth", void 0);
/**
* Sets and gets the options to customize the multi-level labels.
*/
class MultiLevelLabels extends ChildProperty {
}
__decorate([
Property('Center')
], MultiLevelLabels.prototype, "alignment", void 0);
__decorate([
Property('Wrap')
], MultiLevelLabels.prototype, "overflow", void 0);
__decorate([
Complex(Theme.axisLabelFont, Font)
], MultiLevelLabels.prototype, "textStyle", void 0);
__decorate([
Complex({ color: '#b5b5b5', width: 1, type: 'Rectangle' }, AxisLabelBorder)
], MultiLevelLabels.prototype, "border", void 0);
__decorate([
Collection([], MultiLevelCategories)
], MultiLevelLabels.prototype, "categories", void 0);
/**
* Internal class used to maintain colorcollection.
*
* @private
*/
class ColorCollection {
constructor(value, color, label, startValue, endValue, minColor, maxColor) {
this.value = value;
this.color = color;
this.label = label;
this.startValue = startValue;
this.endValue = endValue;
this.minColor = minColor;
this.maxColor = maxColor;
}
}
/**
* Specifies the current data of the bubble cell.
*/
class BubbleTooltipData {
/**
* @param {string} mappingName - Specifies the mapping name.
* @param {number} bubbleData - Specifies the bubble data.
* @param {string} valueType - Specifies the value type.
* @private
*/
constructor(mappingName, bubbleData, valueType) {
this.mappingName = mappingName;
this.bubbleData = bubbleData;
this.valueType = valueType;
}
}
/**
* Internal class used to maintain legend colorcollection.
*
* @private
*/
class LegendColorCollection {
constructor(value, color, label, startValue, endValue, minColor, maxColor, isHidden) {
this.value = value;
this.color = color;
this.label = label;
this.startValue = startValue;
this.endValue = endValue;
this.minColor = minColor;
this.maxColor = maxColor;
this.isHidden = isHidden;
}
}
/**
* class used to maintain xAxis labels details for multipleRow label intersect action.
*
* @private
*/
class MultipleRow {
constructor(start, end, index, label, row) {
this.index = 1;
this.row = 1;
this.start = start;
this.end = end;
this.index = index;
this.label = label;
this.row = row;
}
}
var __decorate$1 = (undefined && undefined.__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;
};
/**
* Sets and gets the options to customize the color palette of heatmap.
*/
class PaletteSettings extends ChildProperty {
}
__decorate$1([
Collection([{}], PaletteCollection)
], PaletteSettings.prototype, "palette", void 0);
__decorate$1([
Property('Gradient')
], PaletteSettings.prototype, "type", void 0);
__decorate$1([
Property('')
], PaletteSettings.prototype, "emptyPointColor", void 0);
__decorate$1([
Property('Table')
], PaletteSettings.prototype, "colorGradientMode", void 0);
__decorate$1([
Complex({}, FillColor)
], PaletteSettings.prototype, "fillColor", void 0);
/**
* Helper class for colormapping
*/
class RgbColor {
constructor(r, g, b) {
this.R = r;
this.G = g;
this.B = b;
}
}
class CellColor {
constructor(heatMap) {
this.heatMap = heatMap;
}
/**
* To convert hexa color to RGB.
*
* @returns {any}
* @private
*/
convertToRGB(value, colorMapping) {
let previousOffset = this.heatMap.isColorRange ? colorMapping[0].startValue : colorMapping[0].value;
let nextOffset = 0;
let i = 0;
let previousColor;
let nextColor;
if (this.heatMap.isColorRange && this.heatMap.paletteSettings.type === 'Gradient') {
for (i = 0; i < colorMapping.length; i++) {
const offset = Number(colorMapping[i].endValue);
if (value <= offset && value >= Number(colorMapping[i].startValue)) {
nextOffset = offset;
previousColor = this.heatMap.colorCollection[i].minColor;
nextColor = this.heatMap.colorCollection[i].maxColor;
}
else if (colorMapping[0].startValue !== this.heatMap.dataSourceMinValue && value < colorMapping[0].startValue) {
nextOffset = colorMapping[0].startValue;
previousOffset = this.heatMap.dataSourceMinValue;
previousColor = this.heatMap.paletteSettings.fillColor.minColor;
nextColor = this.heatMap.paletteSettings.fillColor.maxColor;
break;
}
else if (value > offset && value <= (i === (colorMapping.length - 1) ? this.heatMap.dataSourceMaxValue :
colorMapping[i + 1].startValue)) {
nextOffset = (i === (colorMapping.length - 1)) ? this.heatMap.dataSourceMaxValue : colorMapping[i + 1].startValue;
previousOffset = offset;
previousColor = this.heatMap.paletteSettings.fillColor.minColor;
nextColor = this.heatMap.paletteSettings.fillColor.maxColor;
break;
}
else {
nextOffset = offset;
previousOffset = offset;
}
}
}
else {
for (i = 1; i < colorMapping.length; i++) {
const offset = Number(colorMapping[i].value);
if (value <= offset) {
nextOffset = offset;
previousColor = this.getEqualColor(colorMapping, previousOffset);
nextColor = this.getEqualColor(colorMapping, nextOffset);
break;
}
else {
nextOffset = offset;
previousOffset = offset;
}
}
}
let percent = 0;
const full = (nextOffset) - previousOffset;
percent = (value - previousOffset) / full;
percent = isNaN(percent) || !isFinite(percent) ? 0 : percent;
return this.getPercentageColor(percent, previousColor, nextColor);
}
/**
* To convert RGB to HEX.
*
* @returns {string}
* @private
*/
rgbToHex(r, g, b) {
return '#' + this.componentToHex(r) + this.componentToHex(g) + this.componentToHex(b);
}
/**
* To convert Component to HEX.
*
* @returns {string}
* @private
*/
componentToHex(c) {
const hex = c.toString(16);
return hex.length === 1 ? '0' + hex : hex;
}
/**
* To get similar color.
*
* @returns {string}
* @private
*/
getEqualColor(list, offset) {
for (let i = 0; i < list.length; i++) {
if (Number(list[i].value) === offset) {
let color = list[i].color;
if (!isNullOrUndefined(color)) {
if (color.indexOf('rgb') !== -1) {
color = this.convertToHex(color);
}
else if (color.indexOf('#') === -1) {
color = '#FFFFFF';
}
}
else {
color = '#FFFFFF';
}
return color;
}
}
return '#00000';
}
/**
* To convert RGB to HEX.
*
* @returns {string}
* @private
*/
convertToHex(color) {
let itemColor = color.substr(3);
itemColor = itemColor.split('(')[1].split(')')[0];
const colorSplit = itemColor.split(',');
itemColor = this.rgbToHex(parseInt(colorSplit[0], 10), parseInt(colorSplit[1], 10), parseInt(colorSplit[2], 10));
return itemColor;
}
/**
* To get RGB for percentage value.
*
* @returns {any}
* @private
*/
getPercentageColor(percent, previous, next) {
const nextColor = next.split('#')[1];
const prevColor = previous.split('#')[1];
const r = this.getPercentage(percent, parseInt(prevColor.substr(0, 2), 16), parseInt(nextColor.substr(0, 2), 16));
const g = this.getPercentage(percent, parseInt(prevColor.substr(2, 2), 16), parseInt(nextColor.substr(2, 2), 16));
const b = this.getPercentage(percent, parseInt(prevColor.substr(4, 2), 16), parseInt(nextColor.substr(4, 2), 16));
return new RgbColor(r, g, b);
}
/**
* To convert numbet to percentage.
*
* @returns {any}
* @private
*/
getPercentage(percent, previous, next) {
const full = next - previous;
return Math.round((previous + (full * percent)));
}
/**
* To get complete color Collection.
*
* @private
*/
getColorCollection() {
const heatMap = this.heatMap;
heatMap.colorCollection = [];
heatMap.legendColorCollection = [];
let range;
for (let j = 0; j < this.heatMap.paletteSettings.palette.length; j++) {
if (this.heatMap.paletteSettings.palette[j].startValue === null ||
this.heatMap.paletteSettings.palette[j].endValue === null) {
this.heatMap.isColorRange = false;
break;
}
else {
this.heatMap.isColorRange = true;
}
}
const minValue = heatMap.bubbleSizeWithColor ? heatMap.minColorValue : heatMap.dataSourceMinValue;
const maxValue = heatMap.bubbleSizeWithColor ? heatMap.maxColorValue : heatMap.dataSourceMaxValue;
heatMap.emptyPointColor = heatMap.paletteSettings.emptyPointColor ? heatMap.paletteSettings.emptyPointColor :
heatMap.themeStyle.emptyCellColor;
const tempcolorMapping = this.orderbyOffset(this.heatMap.isColorRange ? heatMap.paletteSettings.palette :
heatMap.paletteSettings.palette && heatMap.paletteSettings.palette.length > 1 ?
heatMap.paletteSettings.palette : heatMap.themeStyle.palette);
if (!tempcolorMapping.isCompact) {
if (heatMap.paletteSettings.type === 'Gradient') {
range = (maxValue - minValue) / (tempcolorMapping.offsets.length - 1);
}
else {
range = (maxValue - minValue) / (tempcolorMapping.offsets.length);
}
if (tempcolorMapping.offsets.length >= 2) {
for (let index = 0; index < tempcolorMapping.offsets.length; index++) {
heatMap.colorCollection.push(new ColorCollection((Math.round(((minValue) + (index * range)) * 100) / 100), tempcolorMapping.offsets[index].color, tempcolorMapping.offsets[index].label, tempcolorMapping.offsets[index].startValue, tempcolorMapping.offsets[index].endValue, tempcolorMapping.offsets[index].minColor, tempcolorMapping.offsets[index].maxColor));
heatMap.legendColorCollection.push(new LegendColorCollection(Math.round(((minValue) + (index * range)) * 100) / 100, tempcolorMapping.offsets[index].color, tempcolorMapping.offsets[index].label, tempcolorMapping.offsets[index].startValue, tempcolorMapping.offsets[index].endValue, tempcolorMapping.offsets[index].minColor, tempcolorMapping.offsets[index].maxColor, false));
}
}
}
else {
heatMap.colorCollection = tempcolorMapping.offsets;
heatMap.legendColorCollection = extend([], tempcolorMapping.offsets, null, true);
}
if (!this.heatMap.isColorRange) {
this.updateLegendColorCollection(minValue, maxValue, tempcolorMapping);
}
}
/**
* To update legend color Collection.
*
* @private
*/
updateLegendColorCollection(minValue, maxValue, tempcolorMapping) {
if (this.heatMap.paletteSettings.type === 'Fixed' && (tempcolorMapping.isCompact || tempcolorMapping.isLabel)) {
return;
}
if (Math.round(minValue * 100) / 100 < this.heatMap.legendColorCollection[0].value) {
this.heatMap.legendColorCollection.unshift(new LegendColorCollection(Math.round(minValue * 100) / 100, this.heatMap.legendColorCollection[0].color, this.heatMap.legendColorCollection[0].label, this.heatMap.legendColorCollection[0].startValue, this.heatMap.legendColorCollection[0].endValue, this.heatMap.legendColorCollection[0].minColor, this.heatMap.legendColorCollection[0].maxColor, true));
}
if (Math.round(maxValue * 100) / 100 > this.heatMap.legendColorCollection[this.heatMap.legendColorCollection.length - 1].value) {
this.heatMap.legendColorCollection.push(new LegendColorCollection(Math.round(maxValue * 100) / 100, this.heatMap.legendColorCollection[this.heatMap.legendColorCollection.length - 1].color, this.heatMap.legendColorCollection[this.heatMap.legendColorCollection.length - 1].label, this.heatMap.legendColorCollection[this.heatMap.legendColorCollection.length - 1].startValue, this.heatMap.legendColorCollection[this.heatMap.legendColorCollection.length - 1].endValue, this.heatMap.legendColorCollection[this.heatMap.legendColorCollection.length - 1].minColor, this.heatMap.legendColorCollection[this.heatMap.legendColorCollection.length - 1].maxColor, true));
}
}
/**
* To get ordered palette color collection.
*
* @private
*/
orderbyOffset(offsets) {
const returnCollection = new PaletterColor();
const key = this.heatMap.isColorRange ? 'to' : 'value';
const label = 'label';
returnCollection.isCompact = true;
returnCollection.isLabel = true;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
returnCollection.offsets = offsets.sort((a, b) => {
if (isNullOrUndefined(a[label]) && isNullOrUndefined(b[label])) {
returnCollection.isLabel = false;
}
if (!isNullOrUndefined(a[key]) && !isNullOrUndefined(b[key])) {
return a[key] - b[key];
}
else {
returnCollection.isCompact = false;
return a;
}
});
if (!returnCollection.isCompact) {
returnCollection.offsets = this.heatMap.paletteSettings.palette && this.heatMap.paletteSettings.palette.length > 1 ?
this.heatMap.paletteSettings.palette : this.heatMap.themeStyle.palette;
}
return returnCollection;
}
/**
* To get color depends to value.
*
* @private
*/
getColorByValue(text) {
let color = '';
let rbg;
let compareValue = 0;
if (text.toString() !== '') {
if (this.heatMap.cellSettings.tileType === 'Bubble' &&
(this.heatMap.cellSettings.bubbleType === 'Size' || this.heatMap.cellSettings.bubbleType === 'Sector')) {
color = this.heatMap.isColorRange ? this.heatMap.colorCollection[0].minColor : this.heatMap.colorCollection[0].color;
}
else if (this.heatMap.paletteSettings.type === 'Fixed') {
for (let y = 0; y < this.heatMap.colorCollection.length; y++) {
compareValue = this.heatMap.isColorRange ? this.heatMap.paletteSettings.palette[y].startValue :
this.heatMap.colorCollection[y + 1] ? this.heatMap.colorCollection[y + 1].value :
this.heatMap.colorCollection[y].value;
const singleValue = this.heatMap.dataSourceMinValue === this.heatMap.dataSourceMaxValue;
if (this.heatMap.isColorRange) {
let legendRange;
if ((text <= this.heatMap.colorCollection[y].endValue &&
text >= this.heatMap.colorCollection[y].startValue)) {
if (this.heatMap.legendVisibilityByCellType) {
legendRange = this.heatMap.legendModule.legendRange;
}
color = (this.heatMap.legendVisibilityByCellType && legendRange[y] &&
!legendRange[y].visible) ?
this.heatMap.themeStyle.toggledColor : this.heatMap.colorCollection[y].minColor;
}
else if (color === '') {
color = this.heatMap.paletteSettings.fillColor.minColor;
}
}
else {
if ((text <= compareValue && singleValue && y === 0) || text < compareValue ||
(text >= compareValue && y === this.heatMap.colorCollection.length - 1)) {
let legendRange;
if (this.heatMap.legendVisibilityByCellType) {
legendRange = this.heatMap.legendModule.legendRange;
}
color = (this.heatMap.legendVisibilityByCellType && legendRange[y] &&
!legendRange[y].visible) ?
this.heatMap.themeStyle.toggledColor : this.heatMap.colorCollection[y].color;
break;
}
}
}
}
else {
if (this.heatMap.paletteSettings.colorGradientMode !== 'Table') {
this.getColorCollection();
}
if (text < this.heatMap.colorCollection[0].value && !this.heatMap.isColorRange) {
color = this.heatMap.colorCollection[0].color;
}
else if (text > this.heatMap.colorCollection[this.heatMap.colorCollection.length - 1].value &&
!this.heatMap.isColorRange) {
color = this.heatMap.colorCollection[this.heatMap.colorCollection.length - 1].color;
}
else {
rbg = this.convertToRGB(text, this.heatMap.colorCollection);
color = this.rgbToHex(rbg.R, rbg.G, rbg.B);
}
}
}
else {
color = this.heatMap.emptyPointColor;
}
return color;
}
/**
* @returns {void}
* @private
*/
destroy() {
this.heatMap = null;
}
}
/**
* Function to check whether target object implement specific interface
*
* @param {string} value - specifies the value
* @param {number} containerSize - specifies the containerSize
* @returns {number} returns the number
* @hidden
*/
function stringToNumber(value, containerSize) {
if (value !== null && value !== undefined) {
return value.indexOf('%') !== -1 ? (containerSize / 100) * parseInt(value, 10) : parseInt(value, 10);
}
return null;
}
/**
* Function to check whether target object implement specific interface
*
* @param {string} text - specifies the text
* @param {FontModel} font - specifies the font
* @returns {Size} returns the number
* @hidden
*/
function measureText(text, font) {
const breakText = text || '';
let htmlObject = document.getElementById('heatmapmeasuretext');
if (htmlObject === null) {
htmlObject = createElement('text', { id: 'heatmapmeasuretext' });
document.body.appendChild(htmlObject);
}
if (typeof (text) === 'string' && (text.indexOf('<') > -1 || text.indexOf('>') > -1)) {
const textArray = text.split(' ');
for (let i = 0; i < textArray.length; i++) {
if (textArray[i].indexOf('<br/>') === -1) {
textArray[i] = textArray[i].replace(/[<>]/g, '&');
}
}
text = textArray.join(' ');
}
htmlObject.innerText = (breakText.indexOf('<br>') > -1 || breakText.indexOf('<br/>') > -1) ? breakText : text;
htmlObject.style.position = 'absolute';
htmlObject.style.visibility = 'hidden';
htmlObject.style.fontSize = (font.size).indexOf('px') !== -1 ? font.size : font.size + 'px';
htmlObject.style.fontWeight = font.fontWeight;
htmlObject.style.fontStyle = font.fontStyle;
htmlObject.style.fontFamily = font.fontFamily;
htmlObject.style.top = '-100';
htmlObject.style.left = '0';
htmlObject.style.whiteSpace = 'nowrap';
// For bootstrap line height issue
htmlObject.style.lineHeight = 'normal';
const clientWidth = htmlObject.clientWidth;
const clientHeight = htmlObject.clientHeight;
removeMeasureElement();
return new Size(clientWidth, clientHeight);
}
/** @private */
class TextElement {
constructor(fontModel, fontColor) {
this['font-size'] = fontModel.size;
this['font-style'] = fontModel.fontStyle.toLowerCase();
this['font-family'] = fontModel.fontFamily;
this['font-weight'] = fontModel.fontWeight.toLowerCase();
this.fill = fontColor ? fontColor : '';
}
}
/**
* Function to check whether target object implement specific interface
*
* @param {number} width - specifies the text
* @param {number} leftPadding - specifies the font
* @param {number} rightPadding - specifies the font
* @param {FontModel} titleStyle - specifies the font
* @returns {number} returns the number
* @hidden
*/
function titlePositionX(width, leftPadding, rightPadding, titleStyle) {
let positionX;
if (titleStyle.textAlignment === 'Near') {
positionX = leftPadding;
}
else if (titleStyle.textAlignment === 'Center') {
positionX = leftPadding + width / 2;
}
else {
positionX = width + leftPadding;
}
return positionX;
}
/**
* Specifies the size information of an element.
*/
class Size {
/**
* @param {number} width - Specifies the width.
* @param {number} height - Specifies the height.
* @private */
constructor(width, height) {
this.width = width;
this.height = height;
}
}
/** @private */
class CustomizeOption {
constructor(id) {
this.id = id;
}
}
/** @private */
class PathOption extends CustomizeOption {
constructor(id, fill, width, color, opacity, dashArray, d) {
super(id);
this.opacity = opacity;
this.fill = fill;
this.stroke = color ? color : '';
this['stroke-width'] = parseFloat(width.toString());
this['stroke-dasharray'] = dashArray;
this.d = d;
}
}
/**
* Function to check whether target object implement specific interface
*
* @param { string | Function } template - Specifies the template
* @param { HeatMap } heatMap - Specifies the heatmap
* @param { HTMLElement } labelTemplate - Specifies the label template
* @param { any } rectPosition - Specifies the rect datas
* @param { any } xLabels - Specifies the xlabels
* @param { any } yLabels - Specifies the ylabels
* @param { number } index - Specifies the index
* @returns {any} templateFunction - returns the size
* @private
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function createLabelTemplate(template, heatMap, labelTemplate, rectPosition,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
xLabels, yLabels, index) {
if (heatMap.enableHtmlSanitizer && typeof template === 'string') {
template = SanitizeHtmlHelper.sanitize(template);
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const templateFunction = getTemplateFunction(template, heatMap);
let rectData = null;
const dataSource = heatMap.dataSource;
if (heatMap.dataSourceSettings.isJsonData && (heatMap.dataSourceSettings.adaptorType === 'Cell' || heatMap.dataSourceSettings.adaptorType === 'Table')) {
// eslint-disable-next-line @typescript-eslint/tslint/config
const yLabelData = heatMap.yAxis.valueType === 'Numeric' ? heatMap.yAxis.labels : yLabels;
// eslint-disable-next-line @typescript-eslint/tslint/config
const xLabelData = heatMap.xAxis.valueType === 'Numeric' ? heatMap.xAxis.labels : xLabels;
// eslint-disable-next-line @typescript-eslint/tslint/config
dataSource.forEach((item) => {
// eslint-disable-next-line @typescript-eslint/tslint/config
const yDataMapping = heatMap.dataSourceSettings.adaptorType === 'Cell' ? Object.keys(item).some((key) => item[key] === yLabelData[rectPosition.yIndex]) : (Object.prototype.hasOwnProperty.call(item, yLabelData[rectPosition.yIndex]));
if (Object.keys(item).some((key) => item[key] === xLabelData[rectPosition.xIndex])
&& yDataMapping) {
rectData = item;
}
});
}
else {
rectData = { value: rectPosition.value, xLabel: xLabels[rectPosition.xIndex], yLabel: yLabels[rectPosition.yIndex] };
}
if (!isNullOrUndefined(templateFunction)) {
const tempElement = templateFunction(rectData, heatMap, templateFunction, heatMap.element.id + '_Template' + index, false);
const templateElement = convertElement(tempElement, heatMap.element.id + '_LabelTemplate_' + index);
templateElement.style.cssText = 'opacity: 1; display: flex; align-items: center; justify-content: center; z-index: 2; position: absolute;' + 'top:' + rectPosition.y + 'px;' + 'left:' + rectPosition.x + 'px;' + 'height:' + rectPosition.height + 'px;' + 'width:' + rectPosition.width + 'px;';
for (let i = 0; i < templateElement.children.length; i++) {
templateElement.children[i].style.pointerEvents = 'none';
}
labelTemplate.appendChild(templateElement);
}
return labelTemplate;
}
/**
* Function to check whether target object implement specific interface
*
* @param { string | Function } template - Specifies the template
* @param { HeatMap } heatMap - Specifies the heatmap
* @returns {any} - returns the size
* @private
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function getTemplateFunction(template, heatMap) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let templateFn = null;
try {
if (typeof template !== 'function' && document.querySelectorAll(template).length) {
templateFn = compile(document.querySelector(template).innerHTML.trim());
// eslint-disable-next-line @typescript-eslint/no-explicit-any
}
else if (heatMap.isVue || heatMap.isVue3) {
templateFn = compile(template);
}
else if (typeof template === 'function') {
templateFn = compile(template);
}
}
catch (e) {
templateFn = compile(template);
}
return templateFn;
}
/**
* Function to check whether target object implement specific interface
*
* @param { HTMLCollection } element - Specifies the heatmap
* @param { string } elementId - Specifies the template
* @returns { HTMLElement } - returns the size
* @private
*/
function convertElement(element, elementId) {
const childElement = createElement('div', {
id: elementId
});
childElement.style.cssText = 'position: absolute;pointer-events: auto;';
let elementLength = element.length;
while (elementLength > 0) {
childElement.appendChild(element[0]);
elementLength--;
}
return childElement;
}
/**
* Class to define currentRect private property.
*
* @private
*/
class CurrentRect {
constructor(x, y, width, height, value, id, xIndex, yIndex, xValue, yValue, visible, displayText, textId, allowCollection) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.value = value;
this.id = id;
this.xIndex = xIndex;
this.yIndex = yIndex;
this.xValue = xValue;
this.yValue = yValue;
this.visible = visible;
this.displayText = displayText;
this.textId = textId;
/** @private */
this.allowCollection = allowCollection;
}
}
/**
* Specifies the details of the selected cells.
*/
class SelectedCellDetails {
/**
* @param {number | BubbleTooltipData} value - Specifies the value.
* @param {string} xLabel - Specifies the x label.
* @param {string} yLabel - Specifies the y label.
* @param {number} xValue - Specifies the x value.
* @param {number} yValue - Specifies the y value.
* @param {Element} cellElement - Specifies the cell element.
* @param {number} xPosition - Specifies the x position.
* @param {number} yPosition - Specifies the y position.
* @param {number} width - Specifies the width.
* @param {number} height - Specifies the height.
* @param {number} x - Specifies the x value.
* @param {number} y - Specifies the y value.
* @private
*/
constructor(value, xLabel, yLabel, xValue, yValue, cellElement, xPosition, yPosition, width, height, x, y) {
this.value = value;
this.xLabel = xLabel;
this.yLabel = yLabel;
this.xValue = xValue;
this.yValue = yValue;
this.cellElement = cellElement;
this.xPosition = xPosition;
this.yPosition = yPosition;
this.width = width;
this.height = height;
this.x = x;
this.y = y;
}
}
/**
* Class to define property to draw rectangle.
*
* @private
*/
class RectOption extends PathOption {
constructor(id, fill, border, opacity, rect, borderColor, rx, ry, transform, dashArray) {
super(id, fill, border.width, borderColor, opacity, dashArray);
this.y = rect.y;
this.x = rect.x;
this.height = rect.height > 0 ? rect.height : 0;
this.width = rect.width > 0 ? rect.width : 0;
this.rx = rx ? rx : 0;
this.ry = ry ? ry : 0;
this.transform = transform ? transform : '';
}
}
/**
* Class to define property to draw circle.
*
* @private
*/
class CircleOption extends PathOption {
constructor(id, fill, border, opacity, borderColor, cx, cy, r) {
super(id, fill, border.width, borderColor, opacity);
this.cx = cx ? cx : 0;
this.cy = cy ? cy : 0;
this.r = r ? r : 0;
}
}
/**
* Helper Class to define property to draw rectangle.
*
* @private
*/
class Rect {
constructor(x, y, width, height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
}
/**
* Class to define property to draw text.
*
* @private
*/
class TextOption extends TextElement {
constructor(id, basic, element, fontColor) {
super(element, fontColor);
this.transform = '';
this['dominant-baseline'] = 'auto';
this.role = 'region';
this.labelRotation = 0;
this.baseline = 'auto';
this.id = id;
this.x = basic.x;
this.y = basic.y;
this['text-anchor'] = basic['text-anchor'];
this.text = basic.text;
this['aria-label'] = basic.text;
this.transform = basic.transform;
this.labelRotation = basic.labelRotation;
this['dominant-baseline'] = basic['dominant-baseline'];
this.baseline = basic.baseline;
this.dy = basic.dy;
}
}
/**
* Helper Class to define property to draw text.
*
* @private
*/
class TextBasic {
constructor(x, y, anchor, text, labelRotation, transform, baseLine, dy) {
this.transform = '';
this['dominant-baseline'] = 'auto';
this.labelRotation = 0;
this.baseline = 'auto';
this.x = x ? x : 0;
this.y = y ? y : 0;
this['text-anchor'] = anchor ? anchor : 'start';
this.text = text ? text : '';
this['aria-label'] = text;
this.transform = transform ? transform : '';
this.labelRotation = labelRotation;
this['dominant-baseline'] = baseLine ? baseLine : 'auto';
this.baseline = baseLine ? baseLine : '';
this.dy = dy ? dy : '';
}
}
/**
* Class to define property to draw line.
*
* @private
*/
class Line {
constructor(x1, y1, x2, y2) {
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
}
}
/**
* Class to define property to draw line.
*
* @private
*/
class LineOption extends PathOption {
constructor(id, line, stroke, strokewidth, opacity, dasharray) {
super(id, null, strokewidth, stroke, opacity, dasharray, null);
this.x1 = line.x1;
this.y1 = line.y1;
this.x2 = line.x2;
this.y2 = line.y2;
}
}
/**
* Properties required to render path.
*
* @private
*/
class PathAttributes extends PathOption {
constructor(id, path, fill, border, borderWidth, opacity, borderColor) {
super(id, fill, borderW