@syncfusion/ej2-treemap 20.1.59 → 20.2.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +0 -14
- package/dist/ej2-treemap.umd.min.js +2 -2
- package/dist/ej2-treemap.umd.min.js.map +1 -1
- package/dist/es6/ej2-treemap.es2015.js +19 -13
- package/dist/es6/ej2-treemap.es2015.js.map +1 -1
- package/dist/es6/ej2-treemap.es5.js +19 -13
- package/dist/es6/ej2-treemap.es5.js.map +1 -1
- package/dist/global/ej2-treemap.min.js +2 -2
- package/dist/global/ej2-treemap.min.js.map +1 -1
- package/dist/global/index.d.ts +1 -1
- package/dist/ts/treemap/layout/legend.ts +991 -0
- package/dist/ts/treemap/layout/render-panel.ts +722 -0
- package/dist/ts/treemap/model/base.ts +800 -0
- package/dist/ts/treemap/model/constants.ts +118 -0
- package/dist/ts/treemap/model/image-export.ts +109 -0
- package/dist/ts/treemap/model/interface.ts +554 -0
- package/dist/ts/treemap/model/pdf-export.ts +103 -0
- package/dist/ts/treemap/model/print.ts +93 -0
- package/dist/ts/treemap/model/theme.ts +202 -0
- package/dist/ts/treemap/treemap.ts +1575 -0
- package/dist/ts/treemap/user-interaction/highlight-selection.ts +530 -0
- package/dist/ts/treemap/user-interaction/tooltip.ts +203 -0
- package/dist/ts/treemap/utils/enum.ts +222 -0
- package/dist/ts/treemap/utils/helper.ts +1181 -0
- package/package.json +11 -11
- package/src/treemap/layout/render-panel.js +17 -12
- package/src/treemap/treemap.js +2 -1
|
@@ -0,0 +1,1575 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/ban-types */
|
|
2
|
+
/* eslint-disable @typescript-eslint/dot-notation */
|
|
3
|
+
/* eslint-disable brace-style */
|
|
4
|
+
/* eslint-disable max-len */
|
|
5
|
+
/**
|
|
6
|
+
* Tree Map Components
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { Component, NotifyPropertyChanges, INotifyPropertyChanged, Property, extend, Ajax } from '@syncfusion/ej2-base';
|
|
10
|
+
import { Complex, Collection, ModuleDeclaration } from '@syncfusion/ej2-base';
|
|
11
|
+
import { Event, EmitType, Internationalization } from '@syncfusion/ej2-base';
|
|
12
|
+
import { SvgRenderer } from '@syncfusion/ej2-svg-base';
|
|
13
|
+
import { isNullOrUndefined, createElement, EventHandler, Browser, remove } from '@syncfusion/ej2-base';
|
|
14
|
+
import { BorderModel, TitleSettingsModel, MarginModel, LevelSettingsModel, FontModel } from './model/base-model';
|
|
15
|
+
import { LeafItemSettingsModel, TooltipSettingsModel, LegendSettingsModel, InitialDrillSettingsModel } from './model/base-model';
|
|
16
|
+
import { HighlightSettingsModel, SelectionSettingsModel } from './model/base-model';
|
|
17
|
+
import { Border, Margin, TitleSettings, LegendSettings, InitialDrillSettings } from './model/base';
|
|
18
|
+
import { SelectionSettings, TooltipSettings, LevelSettings, LeafItemSettings, HighlightSettings } from './model/base';
|
|
19
|
+
import { TreeMapModel } from './treemap-model';
|
|
20
|
+
import { LayoutMode, TreeMapTheme, RenderingMode } from './utils/enum';
|
|
21
|
+
import { ILoadEventArgs, ILoadedEventArgs, IPrintEventArgs } from '../treemap/model/interface';
|
|
22
|
+
import { ILegendItemRenderingEventArgs, ILegendRenderingEventArgs, IItemDataEventArgs } from '../treemap/model/interface';
|
|
23
|
+
import { IItemRenderingEventArgs, IResizeEventArgs, IDoubleClickEventArgs, IRightClickEventArgs } from '../treemap/model/interface';
|
|
24
|
+
import { IItemClickEventArgs, IItemMoveEventArgs, IClickEventArgs, IMouseMoveEventArgs } from '../treemap/model/interface';
|
|
25
|
+
import { IDrillStartEventArgs, IItemSelectedEventArgs, ITreeMapTooltipRenderEventArgs } from '../treemap/model/interface';
|
|
26
|
+
import { IItemHighlightEventArgs, IDrillEndEventArgs, IThemeStyle } from '../treemap/model/interface';
|
|
27
|
+
import { Size, stringToNumber, RectOption, Rect, textTrim, measureText, findChildren, removeElement, setItemTemplateContent } from '../treemap/utils/helper';
|
|
28
|
+
import { removeClassNames, removeShape, textFormatter } from '../treemap/utils/helper';
|
|
29
|
+
import { findPosition, Location, TextOption, renderTextElement, isContainsData, TreeMapAjax } from '../treemap/utils/helper';
|
|
30
|
+
import { load, loaded, itemSelected, drillStart, drillEnd } from '../treemap/model/constants';
|
|
31
|
+
import { itemClick, itemMove, click, mouseMove, resize, doubleClick, rightClick } from '../treemap/model/constants';
|
|
32
|
+
import { LayoutPanel } from './layout/render-panel';
|
|
33
|
+
import { TreeMapTooltip } from './user-interaction/tooltip';
|
|
34
|
+
import { ExportType } from '../treemap/utils/enum';
|
|
35
|
+
import { PdfPageOrientation } from '@syncfusion/ej2-pdf-export';
|
|
36
|
+
import { TreeMapHighlight, TreeMapSelection } from './user-interaction/highlight-selection';
|
|
37
|
+
import { TreeMapLegend } from './layout/legend';
|
|
38
|
+
import { DataManager, Query } from '@syncfusion/ej2-data';
|
|
39
|
+
import { getThemeStyle } from './model/theme';
|
|
40
|
+
import { Print } from './model/print';
|
|
41
|
+
import { ImageExport } from './model/image-export';
|
|
42
|
+
import { PdfExport } from './model/pdf-export';
|
|
43
|
+
/**
|
|
44
|
+
* Represents the treemap component.
|
|
45
|
+
* ```html
|
|
46
|
+
* <div id="container"/>
|
|
47
|
+
* <script>
|
|
48
|
+
* var treemap = new TreeMap();
|
|
49
|
+
* treemap.appendTo("#container");
|
|
50
|
+
* </script>
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
|
|
54
|
+
@NotifyPropertyChanges
|
|
55
|
+
export class TreeMap extends Component<HTMLElement> implements INotifyPropertyChanged {
|
|
56
|
+
//Module Declaration for treemap.
|
|
57
|
+
/**
|
|
58
|
+
* Sets and gets the module that is used to add tooltip in the treemap.
|
|
59
|
+
*/
|
|
60
|
+
public treeMapTooltipModule: TreeMapTooltip;
|
|
61
|
+
/**
|
|
62
|
+
* Sets and gets the module that is used to add highlight functionality in the treemap.
|
|
63
|
+
*/
|
|
64
|
+
public treeMapHighlightModule: TreeMapHighlight;
|
|
65
|
+
/**
|
|
66
|
+
* Sets and gets the module that is used to add selection functionality in the treemap.
|
|
67
|
+
*/
|
|
68
|
+
public treeMapSelectionModule: TreeMapSelection;
|
|
69
|
+
/**
|
|
70
|
+
* Sets and gets the module that is used to add legend in the treemap.
|
|
71
|
+
*/
|
|
72
|
+
public treeMapLegendModule: TreeMapLegend;
|
|
73
|
+
/**
|
|
74
|
+
* Sets and gets the module that is used to add print functionality in the treemap.
|
|
75
|
+
*
|
|
76
|
+
* @private
|
|
77
|
+
*/
|
|
78
|
+
public printModule: Print;
|
|
79
|
+
/**
|
|
80
|
+
* Sets and gets the module that is used to add imageExport functionality in the treemap.
|
|
81
|
+
*
|
|
82
|
+
* @private
|
|
83
|
+
*/
|
|
84
|
+
public imageExportModule: ImageExport;
|
|
85
|
+
/**
|
|
86
|
+
* Sets and gets the module that is used to add pdf export functionality in the treemap.
|
|
87
|
+
*
|
|
88
|
+
* @private
|
|
89
|
+
*/
|
|
90
|
+
public pdfExportModule: PdfExport ;
|
|
91
|
+
/**
|
|
92
|
+
* Enables and disables the print functionality in treemap.
|
|
93
|
+
*
|
|
94
|
+
* @default false
|
|
95
|
+
*/
|
|
96
|
+
@Property(false)
|
|
97
|
+
public allowPrint: boolean;
|
|
98
|
+
/**
|
|
99
|
+
* Enables and disables the export to image functionality in treemap.
|
|
100
|
+
*
|
|
101
|
+
* @default false
|
|
102
|
+
*/
|
|
103
|
+
@Property(false)
|
|
104
|
+
public allowImageExport: boolean;
|
|
105
|
+
/**
|
|
106
|
+
* Enables and disables the export to pdf functionality in treemap.
|
|
107
|
+
*
|
|
108
|
+
* @default false
|
|
109
|
+
*/
|
|
110
|
+
@Property(false)
|
|
111
|
+
public allowPdfExport: boolean;
|
|
112
|
+
/**
|
|
113
|
+
* Sets and gets the width of the treemap component.
|
|
114
|
+
*
|
|
115
|
+
* @default null
|
|
116
|
+
*/
|
|
117
|
+
@Property(null)
|
|
118
|
+
public width: string;
|
|
119
|
+
/**
|
|
120
|
+
* Sets and gets the height of the treemap component.
|
|
121
|
+
*
|
|
122
|
+
* @default null
|
|
123
|
+
*/
|
|
124
|
+
@Property(null)
|
|
125
|
+
public height: string;
|
|
126
|
+
/**
|
|
127
|
+
* Sets and gets the options for customizing the color and width of the treemap border.
|
|
128
|
+
*/
|
|
129
|
+
@Complex<BorderModel>({}, Border)
|
|
130
|
+
public border: BorderModel;
|
|
131
|
+
/**
|
|
132
|
+
* Sets and gets the options for customizing the margin in the treemap component.
|
|
133
|
+
*/
|
|
134
|
+
@Complex<MarginModel>({}, Margin)
|
|
135
|
+
public margin: MarginModel;
|
|
136
|
+
/**
|
|
137
|
+
* Sets and gets the background color of the treemap.
|
|
138
|
+
*/
|
|
139
|
+
@Property(null)
|
|
140
|
+
public background: string;
|
|
141
|
+
/**
|
|
142
|
+
* Sets and gets the options for customizing the theme of the treemap component.
|
|
143
|
+
*/
|
|
144
|
+
@Property('Material')
|
|
145
|
+
public theme: TreeMapTheme;
|
|
146
|
+
/**
|
|
147
|
+
* Sets and gets the options for customizing the title of the treemap component.
|
|
148
|
+
*/
|
|
149
|
+
@Complex<TitleSettingsModel>({}, TitleSettings)
|
|
150
|
+
public titleSettings: TitleSettingsModel;
|
|
151
|
+
/**
|
|
152
|
+
* Specifies the rendering type of layout of the treemap component.
|
|
153
|
+
*/
|
|
154
|
+
@Property('Squarified')
|
|
155
|
+
public layoutType: LayoutMode;
|
|
156
|
+
/**
|
|
157
|
+
* Sets and gets the data source for the treemap component.
|
|
158
|
+
*
|
|
159
|
+
* @isGenericType true
|
|
160
|
+
* @isObservable true
|
|
161
|
+
* @default null
|
|
162
|
+
*/
|
|
163
|
+
@Property(null)
|
|
164
|
+
public dataSource: DataManager | TreeMapAjax | Object[];
|
|
165
|
+
/**
|
|
166
|
+
* Sets and gets the query to select particular data from the shape data.
|
|
167
|
+
* This property is applicable only when the data source is created by data manager.
|
|
168
|
+
*
|
|
169
|
+
* @default null
|
|
170
|
+
*/
|
|
171
|
+
@Property(null)
|
|
172
|
+
public query: Query;
|
|
173
|
+
/**
|
|
174
|
+
* Sets and gets the value path of the weight from the data source, based on which the map item is rendered.
|
|
175
|
+
*/
|
|
176
|
+
@Property(null)
|
|
177
|
+
public weightValuePath: string;
|
|
178
|
+
/**
|
|
179
|
+
* Sets and gets the value path from the data source, based on it color is filled in treemap.
|
|
180
|
+
*/
|
|
181
|
+
@Property('')
|
|
182
|
+
public rangeColorValuePath: string;
|
|
183
|
+
/**
|
|
184
|
+
* Sets and gets the value path from the data source, based on it color is filled in treemap.
|
|
185
|
+
*/
|
|
186
|
+
@Property('')
|
|
187
|
+
public equalColorValuePath: string;
|
|
188
|
+
/**
|
|
189
|
+
* Sets and gets the value path from the data source, based on it color is filled in treemap.
|
|
190
|
+
*/
|
|
191
|
+
@Property(null)
|
|
192
|
+
public colorValuePath: string;
|
|
193
|
+
/**
|
|
194
|
+
* Sets and gets the set of colors to apply in the treemap items.
|
|
195
|
+
*/
|
|
196
|
+
@Property([])
|
|
197
|
+
public palette: string[];
|
|
198
|
+
/**
|
|
199
|
+
* Specifies the rendering direction of layout of the treemap items.
|
|
200
|
+
*
|
|
201
|
+
* @default TopLeftBottomRight
|
|
202
|
+
*/
|
|
203
|
+
@Property('TopLeftBottomRight')
|
|
204
|
+
public renderDirection: RenderingMode;
|
|
205
|
+
/**
|
|
206
|
+
* Enables or disables the drill down functionality in treemap.
|
|
207
|
+
*/
|
|
208
|
+
@Property(false)
|
|
209
|
+
public enableDrillDown: boolean;
|
|
210
|
+
/**
|
|
211
|
+
* Enables or disables the connection text in the header of the treemap.
|
|
212
|
+
*/
|
|
213
|
+
@Property(false)
|
|
214
|
+
public enableBreadcrumb: boolean;
|
|
215
|
+
/**
|
|
216
|
+
* Specifies the connection between the two words.
|
|
217
|
+
*/
|
|
218
|
+
@Property(' - ')
|
|
219
|
+
public breadcrumbConnector: string;
|
|
220
|
+
/**
|
|
221
|
+
* Enables or disables the initial drill in the treemap.
|
|
222
|
+
*/
|
|
223
|
+
@Property(false)
|
|
224
|
+
public drillDownView: boolean;
|
|
225
|
+
/**
|
|
226
|
+
* Specifies the options for customizing the initial drill down in treemap.
|
|
227
|
+
*/
|
|
228
|
+
@Complex<InitialDrillSettingsModel>({}, InitialDrillSettings)
|
|
229
|
+
public initialDrillDown: InitialDrillSettingsModel;
|
|
230
|
+
/**
|
|
231
|
+
* Sets and gets the options for customizing the leaf item of the treemap.
|
|
232
|
+
*/
|
|
233
|
+
@Complex<LeafItemSettingsModel>({}, LeafItemSettings)
|
|
234
|
+
public leafItemSettings: LeafItemSettingsModel;
|
|
235
|
+
/**
|
|
236
|
+
* Sets and gets the options for customizing the levels of the treemap.
|
|
237
|
+
*/
|
|
238
|
+
@Collection<LevelSettingsModel>([], LevelSettings)
|
|
239
|
+
public levels: LevelSettingsModel[];
|
|
240
|
+
/**
|
|
241
|
+
* Sets and gets the options for customizing the highlight of the treemap item on mouse over on the treemap component.
|
|
242
|
+
*/
|
|
243
|
+
@Complex<HighlightSettingsModel>({}, HighlightSettings)
|
|
244
|
+
public highlightSettings: HighlightSettingsModel;
|
|
245
|
+
/**
|
|
246
|
+
* Sets and gets the options for customizing the selection of the treemap item on click event on the treemap component.
|
|
247
|
+
*/
|
|
248
|
+
@Complex<SelectionSettingsModel>({}, SelectionSettings)
|
|
249
|
+
public selectionSettings: SelectionSettingsModel;
|
|
250
|
+
/**
|
|
251
|
+
* Sets and gets the options for customizing the tooltip of the treemap.
|
|
252
|
+
*/
|
|
253
|
+
@Complex<TooltipSettingsModel>({}, TooltipSettings)
|
|
254
|
+
public tooltipSettings: TooltipSettingsModel;
|
|
255
|
+
/**
|
|
256
|
+
* Sets and gets the options for customizing the legend of the treemap.
|
|
257
|
+
*/
|
|
258
|
+
@Complex<LegendSettingsModel>({}, LegendSettings)
|
|
259
|
+
public legendSettings: LegendSettingsModel;
|
|
260
|
+
/**
|
|
261
|
+
* Enables or disables the visibility state of the separator for grouping.
|
|
262
|
+
*
|
|
263
|
+
* @default false
|
|
264
|
+
*/
|
|
265
|
+
@Property(false)
|
|
266
|
+
public useGroupingSeparator: boolean;
|
|
267
|
+
/**
|
|
268
|
+
* Sets and gets the description for treemap.
|
|
269
|
+
*
|
|
270
|
+
* @default null
|
|
271
|
+
*/
|
|
272
|
+
@Property(null)
|
|
273
|
+
public description: string;
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Sets and gets the tab index value for treemap.
|
|
277
|
+
*
|
|
278
|
+
* @default 1
|
|
279
|
+
*/
|
|
280
|
+
@Property(1)
|
|
281
|
+
public tabIndex: number;
|
|
282
|
+
/**
|
|
283
|
+
* Sets and gets format for the texts in the treemap.
|
|
284
|
+
*
|
|
285
|
+
* @default null
|
|
286
|
+
*/
|
|
287
|
+
@Property(null)
|
|
288
|
+
public format: string;
|
|
289
|
+
/**
|
|
290
|
+
* Triggers when the treemap is on load.
|
|
291
|
+
*
|
|
292
|
+
* @event
|
|
293
|
+
*/
|
|
294
|
+
@Event()
|
|
295
|
+
public load: EmitType<ILoadEventArgs>;
|
|
296
|
+
/**
|
|
297
|
+
* Triggers before the prints gets started.
|
|
298
|
+
*
|
|
299
|
+
* @event
|
|
300
|
+
*/
|
|
301
|
+
@Event()
|
|
302
|
+
public beforePrint: EmitType<IPrintEventArgs>;
|
|
303
|
+
/**
|
|
304
|
+
* Triggers after treemap is rendered.
|
|
305
|
+
*
|
|
306
|
+
* @event
|
|
307
|
+
*/
|
|
308
|
+
@Event()
|
|
309
|
+
public loaded: EmitType<ILoadedEventArgs>;
|
|
310
|
+
/**
|
|
311
|
+
* Triggers before item rendering in the treemap component.
|
|
312
|
+
*
|
|
313
|
+
* @event
|
|
314
|
+
*/
|
|
315
|
+
@Event()
|
|
316
|
+
public itemRendering: EmitType<IItemRenderingEventArgs>;
|
|
317
|
+
/**
|
|
318
|
+
* Triggers on performing drill down functionality in the treemap.
|
|
319
|
+
*
|
|
320
|
+
* @event
|
|
321
|
+
*/
|
|
322
|
+
@Event()
|
|
323
|
+
public drillStart: EmitType<IDrillStartEventArgs>;
|
|
324
|
+
/**
|
|
325
|
+
* Triggers after drill down functionality gets completed in the treemap.
|
|
326
|
+
*
|
|
327
|
+
* @event
|
|
328
|
+
*/
|
|
329
|
+
@Event()
|
|
330
|
+
public drillEnd: EmitType<IDrillEndEventArgs>;
|
|
331
|
+
/**
|
|
332
|
+
* Triggers after selecting a treemap item.
|
|
333
|
+
*
|
|
334
|
+
* @event
|
|
335
|
+
*/
|
|
336
|
+
@Event()
|
|
337
|
+
public itemSelected: EmitType<IItemSelectedEventArgs>;
|
|
338
|
+
/**
|
|
339
|
+
* Triggers after highlighting on the treemap item.
|
|
340
|
+
*
|
|
341
|
+
* @event
|
|
342
|
+
*/
|
|
343
|
+
@Event()
|
|
344
|
+
public itemHighlight: EmitType<IItemHighlightEventArgs>;
|
|
345
|
+
/**
|
|
346
|
+
* Triggers on rendering of the tooltip in the treemap component.
|
|
347
|
+
*
|
|
348
|
+
* @event
|
|
349
|
+
*/
|
|
350
|
+
@Event()
|
|
351
|
+
public tooltipRendering: EmitType<ITreeMapTooltipRenderEventArgs>;
|
|
352
|
+
/**
|
|
353
|
+
* Triggers after clicking an item in the treemap.
|
|
354
|
+
*
|
|
355
|
+
* @event
|
|
356
|
+
*/
|
|
357
|
+
@Event()
|
|
358
|
+
public itemClick: EmitType<IItemClickEventArgs>;
|
|
359
|
+
/**
|
|
360
|
+
* Triggers after mouse hover on the treemap item.
|
|
361
|
+
*
|
|
362
|
+
* @event
|
|
363
|
+
*/
|
|
364
|
+
@Event()
|
|
365
|
+
public itemMove: EmitType<IItemMoveEventArgs>;
|
|
366
|
+
/**
|
|
367
|
+
* Triggers after clicking on the treemap.
|
|
368
|
+
*
|
|
369
|
+
* @event
|
|
370
|
+
*/
|
|
371
|
+
@Event()
|
|
372
|
+
public click: EmitType<IItemClickEventArgs>;
|
|
373
|
+
/**
|
|
374
|
+
* Triggers after double clicking on the treemap.
|
|
375
|
+
*
|
|
376
|
+
* @event
|
|
377
|
+
*/
|
|
378
|
+
@Event()
|
|
379
|
+
public doubleClick: EmitType<IDoubleClickEventArgs>;
|
|
380
|
+
/**
|
|
381
|
+
* Triggers after right clicking on the treemap.
|
|
382
|
+
*
|
|
383
|
+
* @event
|
|
384
|
+
*/
|
|
385
|
+
@Event()
|
|
386
|
+
public rightClick: EmitType<IMouseMoveEventArgs>;
|
|
387
|
+
/**
|
|
388
|
+
* Triggers after mouse hover on the treemap.
|
|
389
|
+
*
|
|
390
|
+
* @event
|
|
391
|
+
*/
|
|
392
|
+
@Event()
|
|
393
|
+
public mouseMove: EmitType<IMouseMoveEventArgs>;
|
|
394
|
+
/**
|
|
395
|
+
* Triggers after resizing the treemap component.
|
|
396
|
+
*
|
|
397
|
+
* @event
|
|
398
|
+
*/
|
|
399
|
+
@Event()
|
|
400
|
+
public resize: EmitType<IResizeEventArgs>;
|
|
401
|
+
/**
|
|
402
|
+
* Triggers before rendering each legend item in the treemap.
|
|
403
|
+
*
|
|
404
|
+
* @event
|
|
405
|
+
*/
|
|
406
|
+
@Event()
|
|
407
|
+
public legendItemRendering: EmitType<ILegendItemRenderingEventArgs>;
|
|
408
|
+
/**
|
|
409
|
+
* Triggers before rendering the legend items in the treemap.
|
|
410
|
+
*
|
|
411
|
+
* @event
|
|
412
|
+
* @deprecated
|
|
413
|
+
*/
|
|
414
|
+
@Event()
|
|
415
|
+
public legendRendering: EmitType<ILegendRenderingEventArgs>;
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* resize the treemap
|
|
419
|
+
*/
|
|
420
|
+
private isResize: boolean = false;
|
|
421
|
+
/**
|
|
422
|
+
* svg renderer object.
|
|
423
|
+
*
|
|
424
|
+
* @private
|
|
425
|
+
*/
|
|
426
|
+
public renderer: SvgRenderer;
|
|
427
|
+
/**
|
|
428
|
+
* treemap svg element object
|
|
429
|
+
*
|
|
430
|
+
* @private
|
|
431
|
+
*/
|
|
432
|
+
public svgObject: Element;
|
|
433
|
+
/**
|
|
434
|
+
* Stores the exact size of treemap.
|
|
435
|
+
*
|
|
436
|
+
* @private
|
|
437
|
+
*/
|
|
438
|
+
public availableSize: Size;
|
|
439
|
+
/**
|
|
440
|
+
* Internal use of internationalization instance.
|
|
441
|
+
*
|
|
442
|
+
* @private
|
|
443
|
+
*/
|
|
444
|
+
public intl: Internationalization;
|
|
445
|
+
/**
|
|
446
|
+
* @private
|
|
447
|
+
* Stores the area bounds.
|
|
448
|
+
*/
|
|
449
|
+
public areaRect: Rect;
|
|
450
|
+
/**
|
|
451
|
+
* Define the theme style for treemap components
|
|
452
|
+
*
|
|
453
|
+
* @private
|
|
454
|
+
*/
|
|
455
|
+
public themeStyle: IThemeStyle;
|
|
456
|
+
/**
|
|
457
|
+
* @private
|
|
458
|
+
* Stores the legend bounds.
|
|
459
|
+
*/
|
|
460
|
+
public totalRect: Rect;
|
|
461
|
+
/** @private */
|
|
462
|
+
public layout: LayoutPanel;
|
|
463
|
+
/** @private */
|
|
464
|
+
public orientation: string = 'Horizontal';
|
|
465
|
+
/** @private */
|
|
466
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
467
|
+
public drilledItems: any[] = [];
|
|
468
|
+
/** @private */
|
|
469
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
470
|
+
public drilledLegendItems: any;
|
|
471
|
+
/** @private */
|
|
472
|
+
public currentLevel: number;
|
|
473
|
+
/** @private */
|
|
474
|
+
public isHierarchicalData: boolean = false;
|
|
475
|
+
/** @private */
|
|
476
|
+
private resizeTo: number;
|
|
477
|
+
/** @private */
|
|
478
|
+
private mouseDown: boolean;
|
|
479
|
+
/** @private */
|
|
480
|
+
private drillMouseMove: boolean;
|
|
481
|
+
/** @private */
|
|
482
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
483
|
+
public doubleTapTimer: any;
|
|
484
|
+
/** @private */
|
|
485
|
+
public levelSelection: string[] = [];
|
|
486
|
+
/** @private */
|
|
487
|
+
public legendId: string[] = [];
|
|
488
|
+
/** @private */
|
|
489
|
+
public selectionId: string;
|
|
490
|
+
|
|
491
|
+
/**s
|
|
492
|
+
* Constructor for TreeMap component.
|
|
493
|
+
*/
|
|
494
|
+
// eslint-disable-next-line @typescript-eslint/explicit-member-accessibility
|
|
495
|
+
constructor(options?: TreeMapModel, element?: string | HTMLElement) {
|
|
496
|
+
super(options, element);
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
protected preRender(): void {
|
|
500
|
+
this.trigger(load, { treemap: this }, () => {
|
|
501
|
+
this.initPrivateVariable();
|
|
502
|
+
this.unWireEVents();
|
|
503
|
+
this.createSvg();
|
|
504
|
+
this.wireEVents();
|
|
505
|
+
this.setCulture();
|
|
506
|
+
});
|
|
507
|
+
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
protected render(): void {
|
|
511
|
+
this.renderElements();
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
private renderElements(): void {
|
|
515
|
+
LevelsData.levelsData = null;
|
|
516
|
+
LevelsData.defaultLevelsData = null;
|
|
517
|
+
LevelsData.hierarchyData = null;
|
|
518
|
+
this.createSecondaryElement();
|
|
519
|
+
this.addTabIndex();
|
|
520
|
+
this.themeStyle = getThemeStyle(this.theme);
|
|
521
|
+
this.renderBorder();
|
|
522
|
+
this.renderTitle(this.titleSettings, 'title', null, null);
|
|
523
|
+
if (!isNullOrUndefined(LevelsData.levelsData)) {
|
|
524
|
+
LevelsData.defaultLevelsData = LevelsData.levelsData;
|
|
525
|
+
}
|
|
526
|
+
this.processDataManager();
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
private processDataManager(): void {
|
|
530
|
+
let dataModule: DataManager; let queryModule: Query; let ajaxModule: Ajax;
|
|
531
|
+
let localAjax: TreeMapAjax;
|
|
532
|
+
if (this.dataSource instanceof DataManager) {
|
|
533
|
+
dataModule = this.dataSource;
|
|
534
|
+
queryModule = this.query instanceof Query ? this.query : new Query();
|
|
535
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
536
|
+
const dataManager: Promise<any> = dataModule.executeQuery(queryModule);
|
|
537
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
538
|
+
dataManager.then((e: any) => {
|
|
539
|
+
this.dataSource = e['result'];
|
|
540
|
+
this.renderTreeMapElements();
|
|
541
|
+
});
|
|
542
|
+
} else if (this.dataSource instanceof TreeMapAjax) {
|
|
543
|
+
localAjax = this.dataSource as TreeMapAjax;
|
|
544
|
+
ajaxModule = new Ajax(localAjax.dataOptions, localAjax.type, localAjax.async, localAjax.contentType);
|
|
545
|
+
ajaxModule.onSuccess = (args: string) => {
|
|
546
|
+
this.dataSource = JSON.parse('[' + args + ']')[0];
|
|
547
|
+
this.renderTreeMapElements();
|
|
548
|
+
};
|
|
549
|
+
ajaxModule.send(localAjax.sendData);
|
|
550
|
+
} else {
|
|
551
|
+
this.renderTreeMapElements();
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
private renderTreeMapElements(): void {
|
|
556
|
+
|
|
557
|
+
this.processingData();
|
|
558
|
+
|
|
559
|
+
if (this.treeMapLegendModule && this.legendSettings.visible) {
|
|
560
|
+
|
|
561
|
+
this.treeMapLegendModule.renderLegend();
|
|
562
|
+
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
this.layout.processLayoutPanel();
|
|
566
|
+
|
|
567
|
+
this.element.appendChild(this.svgObject);
|
|
568
|
+
|
|
569
|
+
this.elementChange();
|
|
570
|
+
|
|
571
|
+
this.trigger(loaded, {treemap: this, isResized: this.isResize});
|
|
572
|
+
this.isResize = false;
|
|
573
|
+
|
|
574
|
+
this.renderComplete();
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
protected createSvg(): void {
|
|
578
|
+
if (this.svgObject) {
|
|
579
|
+
while (this.svgObject.childNodes.length > 0) {
|
|
580
|
+
this.svgObject.removeChild(this.svgObject.firstChild);
|
|
581
|
+
}
|
|
582
|
+
if (!this.svgObject.hasChildNodes() && this.svgObject.parentNode) {
|
|
583
|
+
remove(this.svgObject);
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
this.clearTemplate();
|
|
587
|
+
const containerWidth: number = this.element.clientWidth;
|
|
588
|
+
const containerHeight: number = this.element.clientHeight;
|
|
589
|
+
this.availableSize = new Size(
|
|
590
|
+
stringToNumber(this.width, containerWidth) || containerWidth || 600,
|
|
591
|
+
stringToNumber(this.height, containerHeight) || containerHeight || 450
|
|
592
|
+
);
|
|
593
|
+
this.svgObject = this.renderer.createSvg({
|
|
594
|
+
id: this.element.id + '_svg',
|
|
595
|
+
width: this.availableSize.width,
|
|
596
|
+
height: this.availableSize.height
|
|
597
|
+
});
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
|
|
601
|
+
/**
|
|
602
|
+
* To initilize the private varibales of treemap.
|
|
603
|
+
*
|
|
604
|
+
* @returns {void}
|
|
605
|
+
*/
|
|
606
|
+
private initPrivateVariable(): void {
|
|
607
|
+
if (this.element.id === '') {
|
|
608
|
+
const collection: number = document.getElementsByClassName('e-treemap').length;
|
|
609
|
+
this.element.id = 'treemap_control_' + collection;
|
|
610
|
+
}
|
|
611
|
+
this.renderer = new SvgRenderer(this.element.id);
|
|
612
|
+
|
|
613
|
+
this.layout = new LayoutPanel(this);
|
|
614
|
+
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
private createSecondaryElement(): void {
|
|
618
|
+
const secondaryEle: Element = document.getElementById(this.element.id + '_Secondary_Element');
|
|
619
|
+
if (secondaryEle && secondaryEle.childElementCount > 0) {
|
|
620
|
+
secondaryEle.parentNode.removeChild(secondaryEle);
|
|
621
|
+
}
|
|
622
|
+
if (isNullOrUndefined(document.getElementById(this.element.id + '_Secondary_Element'))) {
|
|
623
|
+
const secondaryElement: Element = createElement('div', {
|
|
624
|
+
id: this.element.id + '_Secondary_Element',
|
|
625
|
+
styles: 'position: absolute;z-index:1;'
|
|
626
|
+
});
|
|
627
|
+
this.element.appendChild(secondaryElement);
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
private elementChange(): void {
|
|
632
|
+
if (this.treeMapLegendModule && this.legendSettings.visible && this.treeMapLegendModule.legendGroup && this.layout.layoutGroup
|
|
633
|
+
&& !isNullOrUndefined(this.svgObject) && !isNullOrUndefined(document.getElementById(this.layout.layoutGroup.id))
|
|
634
|
+
&& !isNullOrUndefined(document.getElementById(this.treeMapLegendModule.legendGroup.id))) {
|
|
635
|
+
this.svgObject.insertBefore(this.layout.layoutGroup, this.treeMapLegendModule.legendGroup);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
/**
|
|
640
|
+
* @private
|
|
641
|
+
* Render the treemap border
|
|
642
|
+
*
|
|
643
|
+
* @returns {void}
|
|
644
|
+
*/
|
|
645
|
+
private renderBorder(): void {
|
|
646
|
+
const width: number = this.border.width;
|
|
647
|
+
const borderElement: Element = this.svgObject.querySelector('#' + this.element.id + '_TreeMap_Border');
|
|
648
|
+
if ((this.border.width > 0 || (this.background || this.themeStyle.backgroundColor)) && isNullOrUndefined(borderElement)) {
|
|
649
|
+
const borderRect: RectOption = new RectOption(
|
|
650
|
+
this.element.id + '_TreeMap_Border', this.background || this.themeStyle.backgroundColor, this.border, 1,
|
|
651
|
+
new Rect(width / 2, width / 2, this.availableSize.width - width, this.availableSize.height - width));
|
|
652
|
+
this.svgObject.appendChild(this.renderer.drawRectangle(borderRect) as SVGRectElement);
|
|
653
|
+
} else if (borderElement) {
|
|
654
|
+
borderElement.setAttribute('fill', this.background || this.themeStyle.backgroundColor);
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
private renderTitle(title: TitleSettingsModel, type: string, bounds: Rect, groupEle: Element): void {
|
|
659
|
+
const style: FontModel = title.textStyle;
|
|
660
|
+
let height: number; const titlePadding: number = 10;
|
|
661
|
+
const width: number = (this.availableSize.width - this.margin.right - this.margin.left);
|
|
662
|
+
title.textStyle.fontFamily = this.themeStyle.fontFamily || title.textStyle.fontFamily;
|
|
663
|
+
title.textStyle.size = this.themeStyle.fontSize || title.textStyle.size;
|
|
664
|
+
if (title.text) {
|
|
665
|
+
if (isNullOrUndefined(groupEle)) {
|
|
666
|
+
groupEle = this.renderer.createGroup({ id: this.element.id + '_Title_Group' });
|
|
667
|
+
}
|
|
668
|
+
const trimmedTitle: string = textTrim(width, title.text, style);
|
|
669
|
+
const elementSize: Size = measureText(trimmedTitle, style);
|
|
670
|
+
const rect: Rect = (isNullOrUndefined(bounds)) ? new Rect(
|
|
671
|
+
this.margin.left, this.margin.top, this.availableSize.width, this.availableSize.height) : bounds;
|
|
672
|
+
const location: Location = findPosition(rect, title.alignment, elementSize, type);
|
|
673
|
+
const options: TextOption = new TextOption(
|
|
674
|
+
this.element.id + '_TreeMap_' + type, location.x, location.y, 'start', trimmedTitle
|
|
675
|
+
);
|
|
676
|
+
const titleBounds: Rect = new Rect(location.x, location.y, elementSize.width, elementSize.height);
|
|
677
|
+
const element: Element = renderTextElement(
|
|
678
|
+
options, style, style.color || (type === 'title' ? this.themeStyle.titleFontColor : this.themeStyle.subTitleFontColor),
|
|
679
|
+
groupEle
|
|
680
|
+
);
|
|
681
|
+
element.setAttribute('aria-label', title.description || title.text);
|
|
682
|
+
element.setAttribute('tabindex', (this.tabIndex + (type === 'title' ? 1 : 2)).toString());
|
|
683
|
+
if ((type === 'title' && !title.subtitleSettings.text) || (type === 'subtitle')) {
|
|
684
|
+
height = (this.availableSize.height - titleBounds.y - titlePadding - this.margin.bottom);
|
|
685
|
+
this.areaRect = new Rect(this.margin.left, titleBounds.y + titlePadding, width, height);
|
|
686
|
+
}
|
|
687
|
+
if (type !== 'subtitle' && title.subtitleSettings.text) {
|
|
688
|
+
this.renderTitle(title.subtitleSettings, 'subtitle', titleBounds, groupEle);
|
|
689
|
+
} else {
|
|
690
|
+
this.svgObject.appendChild(groupEle);
|
|
691
|
+
}
|
|
692
|
+
} else {
|
|
693
|
+
height = (this.availableSize.height - this.margin.top - this.margin.bottom);
|
|
694
|
+
this.areaRect = new Rect(this.margin.left, this.margin.top, width, height);
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
|
|
699
|
+
|
|
700
|
+
protected processingData(): void {
|
|
701
|
+
let path: string;
|
|
702
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
703
|
+
this.dataSource = this.dataSource as any[];
|
|
704
|
+
if (!isNullOrUndefined(this.dataSource) && this.dataSource.length > 0 && this.weightValuePath) {
|
|
705
|
+
LevelsData.levelsData = [];
|
|
706
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
707
|
+
this.dataSource.map((data: any) => {
|
|
708
|
+
data[this.weightValuePath] = (data[this.weightValuePath]) ? (data[this.weightValuePath] as string).toString() :
|
|
709
|
+
data[this.weightValuePath];
|
|
710
|
+
});
|
|
711
|
+
this.leafItemSettings.labelPath = this.leafItemSettings.labelPath || this.weightValuePath;
|
|
712
|
+
this.checkIsHierarchicalData();
|
|
713
|
+
if (this.levels.length === 0) {
|
|
714
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
715
|
+
const data: any = {};
|
|
716
|
+
data['level'] = 0;
|
|
717
|
+
path = this.leafItemSettings.labelPath;
|
|
718
|
+
data[path] = [];
|
|
719
|
+
for (let i: number = 0; i < this.dataSource.length; i++) {
|
|
720
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
721
|
+
const child: any[] = findChildren(this.dataSource[i])['values'];
|
|
722
|
+
if (this.isHierarchicalData && child && child.length > 0) {
|
|
723
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
724
|
+
child.forEach((currentData: any, dataIndex: number) => {
|
|
725
|
+
if (currentData[path]) {
|
|
726
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
727
|
+
(<any[]>data[path]).push({
|
|
728
|
+
groupIndex: 0, name: currentData[path], levelOrderName: (currentData[path] as string).toString(),
|
|
729
|
+
data: currentData, weight: currentData[this.weightValuePath]
|
|
730
|
+
});
|
|
731
|
+
}
|
|
732
|
+
});
|
|
733
|
+
} else {
|
|
734
|
+
if (this.dataSource[i][path]) {
|
|
735
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
736
|
+
(<any[]>data[path]).push({
|
|
737
|
+
groupIndex: 0, name: this.dataSource[i][path], levelOrderName: (
|
|
738
|
+
this.dataSource[i][path] as string).toString(), data: this.dataSource[i],
|
|
739
|
+
weight: this.dataSource[i][this.weightValuePath]
|
|
740
|
+
});
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
LevelsData.levelsData.push(data);
|
|
745
|
+
} else {
|
|
746
|
+
if (this.isHierarchicalData) {
|
|
747
|
+
LevelsData.hierarchyData = [];
|
|
748
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
749
|
+
LevelsData.hierarchyData = extend([], this.dataSource, LevelsData.hierarchyData, true) as any[];
|
|
750
|
+
for (let i: number = 0; i < LevelsData.hierarchyData.length; i++) {
|
|
751
|
+
this.processHierarchicalData(LevelsData.hierarchyData[i], i);
|
|
752
|
+
}
|
|
753
|
+
LevelsData.levelsData = LevelsData.hierarchyData;
|
|
754
|
+
} else {
|
|
755
|
+
this.processFlatJsonData();
|
|
756
|
+
if (LevelsData.levelsData.length > 1) {
|
|
757
|
+
this.reOrderLevelData(LevelsData.levelsData.length - 1);
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
path = this.levels[0].groupPath;
|
|
761
|
+
}
|
|
762
|
+
if (!this.isHierarchicalData) {
|
|
763
|
+
this.findTotalWeight(LevelsData.levelsData[0][path], 'Parent');
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
private checkIsHierarchicalData(): void {
|
|
769
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
770
|
+
let child: any[]; this.dataSource = this.dataSource as any[];
|
|
771
|
+
for (let i: number = 0; i < this.dataSource.length; i++) {
|
|
772
|
+
child = findChildren(this.dataSource[i])['values'];
|
|
773
|
+
if (child && child.length) {
|
|
774
|
+
this.isHierarchicalData = true;
|
|
775
|
+
break;
|
|
776
|
+
} else if (i === this.dataSource.length - 1) {
|
|
777
|
+
this.isHierarchicalData = false;
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
783
|
+
private processHierarchicalData(data: any, dataCount: number): void {
|
|
784
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
785
|
+
let childData: any[]; const levelData: any[] = [];
|
|
786
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
787
|
+
let newData: any = {};
|
|
788
|
+
let levelIndex: number;
|
|
789
|
+
const path: string = this.leafItemSettings.labelPath ? this.leafItemSettings.labelPath : this.weightValuePath;
|
|
790
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
791
|
+
const currentData: any = {};
|
|
792
|
+
let level: LevelSettingsModel; let key: string;
|
|
793
|
+
newData = findChildren(data);
|
|
794
|
+
childData = newData ? newData['values'] : null;
|
|
795
|
+
if (childData && childData.length > 0) {
|
|
796
|
+
key = newData['key'];
|
|
797
|
+
for (let i: number = 0; i < this.levels.length; i++) {
|
|
798
|
+
if (key === this.levels[i].groupPath) {
|
|
799
|
+
level = this.levels[i];
|
|
800
|
+
levelIndex = i;
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
for (let j: number = 0; j < childData.length; j++) {
|
|
804
|
+
childData[j]['name'] = childData[j][path];
|
|
805
|
+
childData[j]['levelOrderName'] = (levelIndex === 0 ? childData[j]['name'] :
|
|
806
|
+
data['levelOrderName'] + '#' + childData[j]['name']) + '';
|
|
807
|
+
const childItemLevel: string = childData[j]['levelOrderName']; let childLevel: number;
|
|
808
|
+
if (childItemLevel.search('#') > 0) {
|
|
809
|
+
childLevel = childItemLevel.split('#').length - 1;
|
|
810
|
+
}
|
|
811
|
+
childData[j]['groupIndex'] = isNullOrUndefined(levelIndex) ? childLevel === this.levels.length
|
|
812
|
+
? this.levels.length : childLevel : levelIndex;
|
|
813
|
+
if (levelIndex !== 0) {
|
|
814
|
+
childData[j]['parent'] = data;
|
|
815
|
+
}
|
|
816
|
+
childData[j]['groupName'] = key;
|
|
817
|
+
childData[j]['data'] = childData[j];
|
|
818
|
+
childData[j]['isDrilled'] = false;
|
|
819
|
+
childData[j]['weight'] = childData[j][this.weightValuePath];
|
|
820
|
+
}
|
|
821
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
822
|
+
childData.forEach((currentData: any) => {
|
|
823
|
+
this.processHierarchicalData(currentData, dataCount);
|
|
824
|
+
});
|
|
825
|
+
}
|
|
826
|
+
if (dataCount === LevelsData.hierarchyData.length - 1) {
|
|
827
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
828
|
+
let mainData: any[] = LevelsData.hierarchyData[0][this.levels[0].groupPath];
|
|
829
|
+
for (let k: number = 0; k < LevelsData.hierarchyData.length; k++) {
|
|
830
|
+
childData = findChildren(LevelsData.hierarchyData[k])['values'];
|
|
831
|
+
if (k !== 0 && childData) {
|
|
832
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
833
|
+
childData.forEach((currentData: any) => { mainData.push(currentData); });
|
|
834
|
+
LevelsData.hierarchyData.splice(k, 1);
|
|
835
|
+
k -= 1;
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
mainData = LevelsData.hierarchyData[0][this.levels[0].groupPath];
|
|
839
|
+
for (let l: number = 0; l < mainData.length; l++) {
|
|
840
|
+
newData[this.levels[0].groupPath] = mainData;
|
|
841
|
+
mainData[l]['parent'] = newData;
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
/* eslint-disable valid-jsdoc */
|
|
846
|
+
/**
|
|
847
|
+
* This method is used to perform the print functionality in treemap.
|
|
848
|
+
*
|
|
849
|
+
* @param id - Specifies the element to print the treemap.
|
|
850
|
+
*/
|
|
851
|
+
public print(id?: string[] | string | Element): void {
|
|
852
|
+
if (this.allowPrint && this.printModule) {
|
|
853
|
+
this.printModule.print(id);
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
/**
|
|
857
|
+
* This method is used to perform the export functionality for the rendered treemap.
|
|
858
|
+
*
|
|
859
|
+
* @param type - Specifies the index of the axis.
|
|
860
|
+
* @param fileName - Specifies file name for exporting the rendered treemap.
|
|
861
|
+
* @param orientation - Specifies the orientation of the pdf document.
|
|
862
|
+
*/
|
|
863
|
+
public export(type: ExportType, fileName: string, orientation?: PdfPageOrientation, allowDownload?: boolean): Promise<string> {
|
|
864
|
+
if (isNullOrUndefined(allowDownload)) {
|
|
865
|
+
allowDownload = true;
|
|
866
|
+
}
|
|
867
|
+
if (type === 'PDF' && this.allowPdfExport && this.pdfExportModule) {
|
|
868
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
869
|
+
return new Promise((resolve: any, reject: any) => {
|
|
870
|
+
resolve(this.pdfExportModule.export(type, fileName, orientation, allowDownload));
|
|
871
|
+
});
|
|
872
|
+
|
|
873
|
+
} else if (this.allowImageExport && (type !== 'PDF') && this.imageExportModule) {
|
|
874
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
875
|
+
return new Promise((resolve: any, reject: any) => {
|
|
876
|
+
resolve(this.imageExportModule.export(type, fileName, allowDownload));
|
|
877
|
+
});
|
|
878
|
+
}
|
|
879
|
+
return null;
|
|
880
|
+
}
|
|
881
|
+
private processFlatJsonData(): void {
|
|
882
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
883
|
+
this.dataSource = this.dataSource as any[];
|
|
884
|
+
let groupPath: string; let childGroupPath: string;
|
|
885
|
+
const orderNames: string[] = []; const process: boolean = false;
|
|
886
|
+
for (let i: number = 0; i < this.levels.length + 1; i++) {
|
|
887
|
+
groupPath = this.levels[i] ? this.levels[i].groupPath : this.leafItemSettings.labelPath;
|
|
888
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
889
|
+
const level: any = {};
|
|
890
|
+
level['level'] = i;
|
|
891
|
+
level[groupPath] = [];
|
|
892
|
+
LevelsData.levelsData.push(level);
|
|
893
|
+
for (let j: number = 0; j < this.dataSource.length; j++) {
|
|
894
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
895
|
+
const currentData: any = {}; let childName: string = '';
|
|
896
|
+
if (!isNullOrUndefined(groupPath)) {
|
|
897
|
+
const name: string = this.dataSource[j][groupPath];
|
|
898
|
+
if (i !== 0) {
|
|
899
|
+
for (let k: number = 0; k <= i; k++) {
|
|
900
|
+
const childGroupPath: string = this.levels[k] ? this.levels[k].groupPath : groupPath;
|
|
901
|
+
childName += (this.dataSource[j][childGroupPath]) + ((k === i) ? '' : '#');
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
if (!(orderNames.length > 0 ? orderNames.indexOf(childName ?
|
|
905
|
+
childName : name) !== -1 : false)) {
|
|
906
|
+
currentData['name'] = name;
|
|
907
|
+
currentData['levelOrderName'] = ((childName) ? childName : name) + '';
|
|
908
|
+
currentData['groupIndex'] = i;
|
|
909
|
+
currentData['isDrilled'] = false;
|
|
910
|
+
currentData['groupName'] = groupPath;
|
|
911
|
+
currentData['data'] = this.dataSource[j];
|
|
912
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
913
|
+
(<any[]>LevelsData.levelsData[LevelsData.levelsData.length - 1][groupPath]).push(currentData);
|
|
914
|
+
orderNames.push((childName) ? childName : name);
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
/**
|
|
922
|
+
* This method orders the treemap level data.
|
|
923
|
+
*
|
|
924
|
+
* @param start - Specifies the start value of the treemap level.
|
|
925
|
+
*/
|
|
926
|
+
public reOrderLevelData(start: number): void {
|
|
927
|
+
let currentName: string;
|
|
928
|
+
const currentPath: string = this.levels[start] ? this.levels[start].groupPath : this.leafItemSettings.labelPath;
|
|
929
|
+
const prevPath: string = this.levels[start - 1].groupPath;
|
|
930
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
931
|
+
const currentData: any[] = LevelsData.levelsData[start][currentPath] as any[];
|
|
932
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
933
|
+
const previousData: any[] = LevelsData.levelsData[start - 1][prevPath] as any[];
|
|
934
|
+
for (let i: number = 0; i < currentData.length; i++) {
|
|
935
|
+
currentName = currentData[i]['levelOrderName'] as string;
|
|
936
|
+
for (let j: number = 0; j < previousData.length; j++) {
|
|
937
|
+
previousData[j][currentPath] = isNullOrUndefined(previousData[j][currentPath]) ? [] : previousData[j][currentPath];
|
|
938
|
+
if (this.IsChildHierarchy(currentName.split('#'), (previousData[j]['levelOrderName'] as string).split('#'))) {
|
|
939
|
+
if (isNullOrUndefined(currentData[i]['parent'])) {
|
|
940
|
+
currentData[i]['parent'] = previousData[j];
|
|
941
|
+
}
|
|
942
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
943
|
+
(<any[]>previousData[j][currentPath]).push(currentData[i]);
|
|
944
|
+
break;
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
this.findTotalWeight(LevelsData.levelsData[LevelsData.levelsData.length - 1][currentPath], 'Child');
|
|
949
|
+
LevelsData.levelsData.splice(start, 1);
|
|
950
|
+
if ((start - 1) > 0) {
|
|
951
|
+
this.reOrderLevelData(start - 1);
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
private IsChildHierarchy (current: string[], previous: string[]): boolean {
|
|
956
|
+
let isChild: boolean = false;
|
|
957
|
+
for (let i: number = 0; i < previous.length; i++)
|
|
958
|
+
{
|
|
959
|
+
if (current.length < i || previous[i] !== current[i])
|
|
960
|
+
{
|
|
961
|
+
return false;
|
|
962
|
+
}
|
|
963
|
+
else
|
|
964
|
+
{
|
|
965
|
+
isChild = true;
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
return isChild;
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
/**
|
|
972
|
+
* This method finds the weight value of the treemap level.
|
|
973
|
+
*
|
|
974
|
+
* @param processData - Specifies the treemap data.
|
|
975
|
+
* @param type - Specifies the type of the data.
|
|
976
|
+
*/
|
|
977
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
978
|
+
public findTotalWeight(processData: any[], type: string): void {
|
|
979
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
980
|
+
let totalWeight: number; const childData: any[] = [];
|
|
981
|
+
let levelName: string; const start: number = 0; let split: string[];
|
|
982
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
983
|
+
let groupName: string; const groupObj: any = {};
|
|
984
|
+
for (let i: number = 0; i < processData.length; i++) {
|
|
985
|
+
totalWeight = 0;
|
|
986
|
+
groupName = processData[i]['groupName'];
|
|
987
|
+
split = (processData[i]['levelOrderName'] as string).split('#');
|
|
988
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
989
|
+
(<any[]>this.dataSource).forEach((data: any) => {
|
|
990
|
+
if (isContainsData(split, processData[i]['levelOrderName'], data, this)) {
|
|
991
|
+
totalWeight += parseFloat(data[this.weightValuePath]);
|
|
992
|
+
}
|
|
993
|
+
});
|
|
994
|
+
if (type === 'Parent') {
|
|
995
|
+
groupObj[groupName] = processData;
|
|
996
|
+
processData[i]['parent'] = groupObj;
|
|
997
|
+
}
|
|
998
|
+
processData[i]['weight'] = totalWeight;
|
|
999
|
+
}
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
/**
|
|
1003
|
+
* To unbind event handlers for treemap.
|
|
1004
|
+
*
|
|
1005
|
+
* @returns {void}
|
|
1006
|
+
*/
|
|
1007
|
+
private unWireEVents(): void {
|
|
1008
|
+
EventHandler.remove(this.element, 'click', this.clickOnTreeMap);
|
|
1009
|
+
EventHandler.remove(this.element, 'dblclick', this.doubleClickOnTreeMap);
|
|
1010
|
+
EventHandler.remove(this.element, 'contextmenu', this.rightClickOnTreeMap);
|
|
1011
|
+
EventHandler.remove(this.element, Browser.touchStartEvent, this.mouseDownOnTreeMap);
|
|
1012
|
+
EventHandler.remove(this.element, Browser.touchMoveEvent, this.mouseMoveOnTreeMap);
|
|
1013
|
+
EventHandler.remove(this.element, Browser.touchEndEvent, this.mouseEndOnTreeMap);
|
|
1014
|
+
EventHandler.remove(this.element, 'pointerleave mouseleave', this.mouseLeaveOnTreeMap);
|
|
1015
|
+
window.removeEventListener('resize', this.resizeOnTreeMap);
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
/**
|
|
1019
|
+
* To bind event handlers for treemap.
|
|
1020
|
+
*
|
|
1021
|
+
* @returns {void}
|
|
1022
|
+
*/
|
|
1023
|
+
private wireEVents(): void {
|
|
1024
|
+
EventHandler.add(this.element, 'click', this.clickOnTreeMap, this);
|
|
1025
|
+
EventHandler.add(this.element, 'dblclick', this.doubleClickOnTreeMap, this);
|
|
1026
|
+
EventHandler.add(this.element, 'contextmenu', this.rightClickOnTreeMap, this);
|
|
1027
|
+
EventHandler.add(this.element, Browser.touchStartEvent, this.mouseDownOnTreeMap, this);
|
|
1028
|
+
EventHandler.add(this.element, Browser.touchMoveEvent, this.mouseMoveOnTreeMap, this);
|
|
1029
|
+
EventHandler.add(this.element, Browser.touchEndEvent, this.mouseEndOnTreeMap, this);
|
|
1030
|
+
EventHandler.add(this.element, 'pointerleave mouseleave', this.mouseLeaveOnTreeMap, this);
|
|
1031
|
+
window.addEventListener('resize', this.resizeOnTreeMap.bind(this));
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
/**
|
|
1035
|
+
* Method to set culture for maps
|
|
1036
|
+
*
|
|
1037
|
+
* @returns {void}
|
|
1038
|
+
*/
|
|
1039
|
+
private setCulture(): void {
|
|
1040
|
+
this.intl = new Internationalization();
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
/**
|
|
1044
|
+
* To add tab index for treemap element
|
|
1045
|
+
*
|
|
1046
|
+
* @returns {void}
|
|
1047
|
+
*/
|
|
1048
|
+
private addTabIndex(): void {
|
|
1049
|
+
this.element.setAttribute('aria-label', this.description || 'TreeMap Element');
|
|
1050
|
+
this.element.setAttribute('tabindex', this.tabIndex.toString());
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
/**
|
|
1054
|
+
* This method handles the window resize event on treemap.
|
|
1055
|
+
*
|
|
1056
|
+
* @param e - Specifies the pointer event.
|
|
1057
|
+
*/
|
|
1058
|
+
public resizeOnTreeMap(e: Event): void {
|
|
1059
|
+
this.isResize = true;
|
|
1060
|
+
let args: IResizeEventArgs = {
|
|
1061
|
+
name: resize,
|
|
1062
|
+
cancel: false,
|
|
1063
|
+
previousSize: this.availableSize,
|
|
1064
|
+
currentSize: new Size(0, 0),
|
|
1065
|
+
treemap: this
|
|
1066
|
+
};
|
|
1067
|
+
if (this.resizeTo) {
|
|
1068
|
+
clearTimeout(this.resizeTo);
|
|
1069
|
+
}
|
|
1070
|
+
if (!isNullOrUndefined(this.element) && this.element.classList.contains('e-treemap')) {
|
|
1071
|
+
this.resizeTo = setTimeout(
|
|
1072
|
+
(): void => {
|
|
1073
|
+
this.unWireEVents();
|
|
1074
|
+
this.createSvg();
|
|
1075
|
+
this.refreshing = true;
|
|
1076
|
+
this.wireEVents();
|
|
1077
|
+
args.currentSize = this.availableSize;
|
|
1078
|
+
this.trigger(resize, args, (observedArgs: IResizeEventArgs) => {
|
|
1079
|
+
this.render();
|
|
1080
|
+
});
|
|
1081
|
+
},
|
|
1082
|
+
500);
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
/**
|
|
1087
|
+
* This method handles the click event on the treemap.
|
|
1088
|
+
*
|
|
1089
|
+
* @param e - Specifies the mouse click event in the treemap.
|
|
1090
|
+
*/
|
|
1091
|
+
public clickOnTreeMap(e: PointerEvent): void {
|
|
1092
|
+
const targetEle: Element = <Element>e.target;
|
|
1093
|
+
const targetId: string = targetEle.id;
|
|
1094
|
+
let eventArgs: IItemClickEventArgs;
|
|
1095
|
+
let itemIndex: number;
|
|
1096
|
+
const labelText : string = targetEle.innerHTML;
|
|
1097
|
+
const clickArgs: IClickEventArgs = { cancel: false, name: click, treemap: this, mouseEvent: e };
|
|
1098
|
+
this.trigger(click, clickArgs);
|
|
1099
|
+
if (targetId.indexOf('_Item_Index') > -1) {
|
|
1100
|
+
e.preventDefault();
|
|
1101
|
+
itemIndex = parseFloat(targetId.split('_Item_Index_')[1]);
|
|
1102
|
+
eventArgs = {
|
|
1103
|
+
cancel: false, name: itemClick, treemap: this, item: this.layout.renderItems[itemIndex], mouseEvent: e,
|
|
1104
|
+
groupIndex: this.layout.renderItems[itemIndex]['groupIndex'], groupName: this.layout.renderItems[itemIndex]['name'],
|
|
1105
|
+
text: labelText, contentItemTemplate : labelText
|
|
1106
|
+
};
|
|
1107
|
+
this.trigger(itemClick, eventArgs, (observedArgs: IItemClickEventArgs) => {
|
|
1108
|
+
if (observedArgs.text !== labelText || observedArgs.contentItemTemplate !== labelText) {
|
|
1109
|
+
if (isNullOrUndefined(this.leafItemSettings.labelTemplate)) {
|
|
1110
|
+
observedArgs.text = textFormatter(observedArgs.text, observedArgs['item']['data'], observedArgs.treemap);
|
|
1111
|
+
targetEle.innerHTML = observedArgs.text;
|
|
1112
|
+
} else {
|
|
1113
|
+
setItemTemplateContent(targetId, targetEle, observedArgs.contentItemTemplate);
|
|
1114
|
+
}
|
|
1115
|
+
}
|
|
1116
|
+
});
|
|
1117
|
+
}
|
|
1118
|
+
const end: number = new Date().getMilliseconds();
|
|
1119
|
+
let doubleTapTimer1: number;
|
|
1120
|
+
if (!isNullOrUndefined(this.doubleClick)) {
|
|
1121
|
+
if (!isNullOrUndefined(doubleTapTimer1) && end - doubleTapTimer1 < 500) {
|
|
1122
|
+
this.doubleClickOnTreeMap(e);
|
|
1123
|
+
}
|
|
1124
|
+
doubleTapTimer1 = end;
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
/**
|
|
1130
|
+
* This method handles the double click event in the treemap.
|
|
1131
|
+
*
|
|
1132
|
+
* @param e - Specifies the pointer event of mouse click.
|
|
1133
|
+
*/
|
|
1134
|
+
public doubleClickOnTreeMap(e: PointerEvent): void {
|
|
1135
|
+
const doubleClickArgs: IDoubleClickEventArgs = { cancel: false, name: doubleClick, treemap: this, mouseEvent: e };
|
|
1136
|
+
this.trigger(doubleClick, doubleClickArgs);
|
|
1137
|
+
//this.notify('dblclick', e);
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
/**
|
|
1141
|
+
* This method handles the right click event in the treemap.
|
|
1142
|
+
*
|
|
1143
|
+
* @param e - Specifies the pointer event of mouse click.
|
|
1144
|
+
*/
|
|
1145
|
+
public rightClickOnTreeMap(e: PointerEvent): void {
|
|
1146
|
+
const rightClickArgs: IRightClickEventArgs = { cancel: false, name: rightClick, treemap: this, mouseEvent: e };
|
|
1147
|
+
this.trigger(rightClick, rightClickArgs);
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
|
|
1151
|
+
/**
|
|
1152
|
+
* This method handles the mouse down event in the treemap.
|
|
1153
|
+
*
|
|
1154
|
+
* @param e - Specifies the pointer event of mouse click.
|
|
1155
|
+
*/
|
|
1156
|
+
public mouseDownOnTreeMap(e: PointerEvent): void {
|
|
1157
|
+
if ((<Element>e.target).id.indexOf('_Item_Index') > -1) {
|
|
1158
|
+
this.mouseDown = true;
|
|
1159
|
+
}
|
|
1160
|
+
this.notify(Browser.touchStartEvent, e);
|
|
1161
|
+
}
|
|
1162
|
+
|
|
1163
|
+
/**
|
|
1164
|
+
* This method handles the mouse move event in the treemap.
|
|
1165
|
+
*
|
|
1166
|
+
* @param e - Specifies the pointer event of mouse click.
|
|
1167
|
+
*/
|
|
1168
|
+
public mouseMoveOnTreeMap(e: PointerEvent): void {
|
|
1169
|
+
const targetEle: Element = <Element>e.target;
|
|
1170
|
+
const targetId: string = targetEle.id;
|
|
1171
|
+
let eventArgs: IItemMoveEventArgs;
|
|
1172
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1173
|
+
let item: any;
|
|
1174
|
+
const moveArgs: IMouseMoveEventArgs = { cancel: false, name: mouseMove, treemap: this, mouseEvent: e };
|
|
1175
|
+
this.trigger(mouseMove, moveArgs);
|
|
1176
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1177
|
+
let childItems: any[];
|
|
1178
|
+
if (targetId.indexOf('_Item_Index') > -1) {
|
|
1179
|
+
item = this.layout.renderItems[parseFloat(targetId.split('_Item_Index_')[1])];
|
|
1180
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1181
|
+
childItems = findChildren(item)['values'] as any[];
|
|
1182
|
+
this.element.style.cursor = (!item['isLeafItem'] && childItems && childItems.length > 0 && this.enableDrillDown) ?
|
|
1183
|
+
'pointer' : 'auto';
|
|
1184
|
+
eventArgs = { cancel: false, name: itemMove, treemap: this, item: item, mouseEvent: e };
|
|
1185
|
+
this.trigger(itemMove, eventArgs);
|
|
1186
|
+
}
|
|
1187
|
+
this.notify(Browser.touchMoveEvent, e);
|
|
1188
|
+
}
|
|
1189
|
+
|
|
1190
|
+
/**
|
|
1191
|
+
* This method calculates the selected treemap levels.
|
|
1192
|
+
*
|
|
1193
|
+
* @param labelText - Specifies the label text.
|
|
1194
|
+
* @param item - Specifies the treemap item.
|
|
1195
|
+
*/
|
|
1196
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1197
|
+
public calculateSelectedTextLevels(labelText: string, item: any): any {
|
|
1198
|
+
//to find the levels by clicking the particular text both for drillDownView as true / false.
|
|
1199
|
+
let drillLevel: number; let k: string; let text: String;
|
|
1200
|
+
const levelLabels: string = item['levelOrderName'];
|
|
1201
|
+
const levelText: string[] = levelLabels.split('#');
|
|
1202
|
+
for (k of Object.keys(levelText)) {
|
|
1203
|
+
if (levelText[k] === labelText) {
|
|
1204
|
+
drillLevel = parseInt(k, 10);
|
|
1205
|
+
text = labelText;
|
|
1206
|
+
}
|
|
1207
|
+
}
|
|
1208
|
+
return { drillLevel: drillLevel, currentLevelLabel: text, levelText: levelText };
|
|
1209
|
+
}
|
|
1210
|
+
|
|
1211
|
+
/**
|
|
1212
|
+
* This method calculates the previous level of child items in treemap.
|
|
1213
|
+
*
|
|
1214
|
+
* @param labelText - Specifies the label text in treemap
|
|
1215
|
+
* @param drillLevelValues - Specifies the values of drill level.
|
|
1216
|
+
* @param item - Specifies the treemap item.
|
|
1217
|
+
* @param directLevel - Specifies the current level.
|
|
1218
|
+
*/
|
|
1219
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1220
|
+
public calculatePreviousLevelChildItems(labelText: string, drillLevelValues: any, item: any, directLevel: boolean): boolean {
|
|
1221
|
+
//By clicking any child items drilldown to the particular level.
|
|
1222
|
+
//At the time store all the previous drilled level items in drilledItems
|
|
1223
|
+
// This condition satisfies while drilldown View is set as false and the text contains '[+]'
|
|
1224
|
+
let text: string; let p: number = 0; let levelItems: string; let text1: string;
|
|
1225
|
+
const drillTextLevel: number = this.layout.renderItems[0]['levelOrderName'].split('#').length;
|
|
1226
|
+
for (let h: number = 0; h < drillTextLevel; h++) {
|
|
1227
|
+
text1 = h === 0 ? drillLevelValues['levelText'][h] : text1 + '#' + drillLevelValues['levelText'][h];
|
|
1228
|
+
}
|
|
1229
|
+
p = drillTextLevel > 1 ? drillTextLevel : p;
|
|
1230
|
+
for (levelItems of Object['values'](this.layout.renderItems)) {
|
|
1231
|
+
const drillLevelText: string = levelItems['levelOrderName'].split('#');
|
|
1232
|
+
if (drillLevelText[0] === drillLevelValues['levelText'][0]) {
|
|
1233
|
+
text = p === 0 ? isNullOrUndefined(text1) ? text1 : drillLevelValues['levelText'][p] :
|
|
1234
|
+
directLevel ? text1 : text1 + '#' + drillLevelValues['levelText'][p];
|
|
1235
|
+
if (text === levelItems['levelOrderName']) {
|
|
1236
|
+
this.drilledItems.push({ name: levelItems['levelOrderName'], data: levelItems });
|
|
1237
|
+
p++;
|
|
1238
|
+
directLevel = true;
|
|
1239
|
+
if (p <= item['groupIndex']) {
|
|
1240
|
+
text = text + '#' + drillLevelValues['levelText'][p];
|
|
1241
|
+
text1 = text;
|
|
1242
|
+
}
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
return directLevel;
|
|
1247
|
+
}
|
|
1248
|
+
|
|
1249
|
+
/**
|
|
1250
|
+
* This method compares the selected labels with the drill down items.
|
|
1251
|
+
*
|
|
1252
|
+
* @param drillLevelValues - Specifies the values of drill level.
|
|
1253
|
+
* @param item - Specifies the treemap item.
|
|
1254
|
+
* @param i - Specifies the treemap item.
|
|
1255
|
+
*/
|
|
1256
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1257
|
+
public compareSelectedLabelWithDrillDownItems(drillLevelValues: any, item: any, i: number): any {
|
|
1258
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1259
|
+
let drillLevelChild: any; const newDrillItem: any = {};
|
|
1260
|
+
const b: number = drillLevelValues['drillLevel'] + 1;
|
|
1261
|
+
if (b === this.drilledItems[i]['data']['groupIndex']) {
|
|
1262
|
+
drillLevelChild = this.drilledItems[i]['data']['parent'];
|
|
1263
|
+
drillLevelChild['isDrilled'] = true;
|
|
1264
|
+
newDrillItem[drillLevelChild[this.drilledItems[i]['data']['groupName']]]
|
|
1265
|
+
= [drillLevelChild];
|
|
1266
|
+
// to remove all the items after matched drilled items
|
|
1267
|
+
this.drilledItems.splice(i, this.drilledItems.length);
|
|
1268
|
+
} else if (drillLevelValues['drillLevel'] === (this.drilledItems.length - 1)
|
|
1269
|
+
|| drillLevelValues['drillLevel'] === item['groupIndex']) {
|
|
1270
|
+
newDrillItem[item['groupName']] = [item];
|
|
1271
|
+
}
|
|
1272
|
+
return newDrillItem;
|
|
1273
|
+
}
|
|
1274
|
+
|
|
1275
|
+
/**
|
|
1276
|
+
* This method handles mouse end event in treemap.
|
|
1277
|
+
*
|
|
1278
|
+
* @param e - Specifies the pointer event of mouse.
|
|
1279
|
+
*/
|
|
1280
|
+
public mouseEndOnTreeMap(e: PointerEvent): void {
|
|
1281
|
+
const targetEle: Element = <Element>e.target; const targetId: string = targetEle.id; let totalRect: Rect;
|
|
1282
|
+
let startEvent: IDrillStartEventArgs; let endEvent: IDrillEndEventArgs; let directLevel: boolean = false;
|
|
1283
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1284
|
+
let index: number; let newDrillItem: any = {}; let item: any; const process: boolean = true;
|
|
1285
|
+
const layoutID: string = this.element.id + '_TreeMap_' + this.layoutType + '_Layout'; let drillLevel: number;
|
|
1286
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1287
|
+
const templateID: string = this.element.id + '_Label_Template_Group'; let drillLevelValues: any;
|
|
1288
|
+
if (targetId.indexOf('_Item_Index') > -1 && this.enableDrillDown && !this.drillMouseMove) {
|
|
1289
|
+
if (e.cancelable) {
|
|
1290
|
+
e.preventDefault();
|
|
1291
|
+
}
|
|
1292
|
+
index = parseFloat(targetId.split('_Item_Index_')[1]);
|
|
1293
|
+
item = this.layout.renderItems[index];
|
|
1294
|
+
const labelText: string = targetEle.innerHTML;
|
|
1295
|
+
if (this.enableBreadcrumb) {
|
|
1296
|
+
drillLevelValues = this.calculateSelectedTextLevels(labelText, item);
|
|
1297
|
+
drillLevel = drillLevelValues['drillLevel'];
|
|
1298
|
+
if (!this.drillDownView && labelText.search('[+]') !== -1) {
|
|
1299
|
+
directLevel = this.calculatePreviousLevelChildItems(labelText, drillLevelValues, item, directLevel);
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1302
|
+
if (this.levels.length !== 0 && !item['isLeafItem'] && findChildren(item)['values'] &&
|
|
1303
|
+
findChildren(item)['values'].length > 0) {
|
|
1304
|
+
if (this.drilledItems.length > 0) {
|
|
1305
|
+
item = directLevel ? this.drilledItems[this.drilledItems.length - 1]['data'] : item;
|
|
1306
|
+
for (let i: number = 0; i < this.drilledItems.length; i++) {
|
|
1307
|
+
if (!isNullOrUndefined(drillLevel)) { //Compare the selected text level with drilled items
|
|
1308
|
+
const drillLength: number = this.drilledItems.length;
|
|
1309
|
+
newDrillItem = this.compareSelectedLabelWithDrillDownItems(drillLevelValues, item, i);
|
|
1310
|
+
if (drillLength !== this.drilledItems.length) {
|
|
1311
|
+
i -= 1; break;
|
|
1312
|
+
}
|
|
1313
|
+
} //when clicking the levels drill back to the previous level process takes place
|
|
1314
|
+
if (item['levelOrderName'] === this.drilledItems[i]['name'] && !directLevel && isNullOrUndefined(drillLevel)) {
|
|
1315
|
+
if (item['groupIndex'] === 0 && item['parent'][item['groupName']] instanceof Array) {
|
|
1316
|
+
item['isDrilled'] = !(item['isDrilled']);
|
|
1317
|
+
if (!item['isDrilled']) {
|
|
1318
|
+
newDrillItem = item['parent'];
|
|
1319
|
+
} else {
|
|
1320
|
+
newDrillItem[item['groupName']] = [item];
|
|
1321
|
+
}
|
|
1322
|
+
} else {
|
|
1323
|
+
item['isDrilled'] = false; item['parent']['isDrilled'] = true; item = item['parent'];
|
|
1324
|
+
newDrillItem[item['groupName']] = [item];
|
|
1325
|
+
}
|
|
1326
|
+
this.drilledItems.splice(i, 1);
|
|
1327
|
+
i -= 1; break;
|
|
1328
|
+
} else if (i === this.drilledItems.length - 1 && isNullOrUndefined(drillLevel)) {
|
|
1329
|
+
item['isDrilled'] = true; // click the items move to next level.
|
|
1330
|
+
newDrillItem[item['groupName']] = [item];
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
} else {
|
|
1334
|
+
item['isDrilled'] = true;
|
|
1335
|
+
newDrillItem[item['groupName']] = [item];
|
|
1336
|
+
}
|
|
1337
|
+
startEvent = {
|
|
1338
|
+
cancel: false, name: drillStart, treemap: this,
|
|
1339
|
+
element: targetEle, groupIndex: this.enableBreadcrumb &&
|
|
1340
|
+
this.drilledItems.length !== 0 && !isNullOrUndefined(drillLevel) ?
|
|
1341
|
+
this.drilledItems[this.drilledItems.length - 1]['data']['groupIndex'] : item['groupIndex'],
|
|
1342
|
+
groupName: this.enableBreadcrumb && this.drilledItems.length !== 0 && !isNullOrUndefined(drillLevel) ?
|
|
1343
|
+
this.drilledItems[this.drilledItems.length - 1]['data']['name'] : item['name'],
|
|
1344
|
+
rightClick: e.which === 3 ? true : false, childItems: null, item: newDrillItem
|
|
1345
|
+
};
|
|
1346
|
+
this.trigger(drillStart, startEvent, (observedArgs: IDrillStartEventArgs) => {
|
|
1347
|
+
this.currentLevel = item['isDrilled'] && isNullOrUndefined(drillLevel) ? item['groupIndex'] :
|
|
1348
|
+
(!isNullOrUndefined(drillLevel) && this.enableBreadcrumb && item['isDrilled']) ? drillLevel : null;
|
|
1349
|
+
if (!observedArgs.cancel) {
|
|
1350
|
+
if (document.getElementById(layoutID)) {
|
|
1351
|
+
const layerElementId: HTMLElement = document.getElementById(layoutID);
|
|
1352
|
+
layerElementId.parentNode.removeChild(layerElementId);
|
|
1353
|
+
}
|
|
1354
|
+
totalRect = extend({}, this.areaRect, totalRect, true) as Rect;
|
|
1355
|
+
if (this.legendSettings.visible && !isNullOrUndefined(this.treeMapLegendModule)) {
|
|
1356
|
+
if (!isNullOrUndefined(newDrillItem)) {
|
|
1357
|
+
this.treeMapLegendModule.legendGroup.textContent = ''; this.treeMapLegendModule.legendGroup = null;
|
|
1358
|
+
this.treeMapLegendModule.widthIncrement = 0; this.treeMapLegendModule.heightIncrement = 0;
|
|
1359
|
+
if (this.enableBreadcrumb && !isNullOrUndefined(drillLevel)) {
|
|
1360
|
+
this.drilledLegendItems = {
|
|
1361
|
+
name: this.drilledItems[this.drilledItems.length - 1]['data']['levelOrderName'],
|
|
1362
|
+
data: this.drilledItems[this.drilledItems.length - 1]['data']
|
|
1363
|
+
};
|
|
1364
|
+
} else {
|
|
1365
|
+
this.drilledLegendItems = { name: item['levelOrderName'], data: item };
|
|
1366
|
+
}
|
|
1367
|
+
this.treeMapLegendModule.renderLegend();
|
|
1368
|
+
}
|
|
1369
|
+
totalRect = !isNullOrUndefined(this.totalRect) ? this.totalRect : totalRect;
|
|
1370
|
+
}
|
|
1371
|
+
if (document.getElementById(templateID)) {
|
|
1372
|
+
const drillElementId: HTMLElement = document.getElementById(templateID);
|
|
1373
|
+
drillElementId.parentNode.removeChild(drillElementId);
|
|
1374
|
+
}
|
|
1375
|
+
if (!isNullOrUndefined(observedArgs.childItems) && !observedArgs.cancel) {
|
|
1376
|
+
this.layout.onDemandProcess(observedArgs.childItems);
|
|
1377
|
+
} else {
|
|
1378
|
+
this.layout.calculateLayoutItems(newDrillItem, totalRect);
|
|
1379
|
+
this.layout.renderLayoutItems(newDrillItem);
|
|
1380
|
+
}
|
|
1381
|
+
}
|
|
1382
|
+
});
|
|
1383
|
+
endEvent = { cancel: false, name: drillEnd, treemap: this, renderItems: this.layout.renderItems };
|
|
1384
|
+
this.trigger(drillEnd, endEvent);
|
|
1385
|
+
if (process) {
|
|
1386
|
+
if (!directLevel && isNullOrUndefined(drillLevel)) {
|
|
1387
|
+
this.drilledItems.push({ name: item['levelOrderName'], data: item });
|
|
1388
|
+
}
|
|
1389
|
+
}
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
this.mouseDown = false;
|
|
1393
|
+
this.notify(Browser.touchEndEvent, e);
|
|
1394
|
+
}
|
|
1395
|
+
|
|
1396
|
+
/**
|
|
1397
|
+
* This method handles mouse leave event in treemap.
|
|
1398
|
+
*
|
|
1399
|
+
* @param e - Specifies the pointer event of mouse.
|
|
1400
|
+
*/
|
|
1401
|
+
public mouseLeaveOnTreeMap(e: PointerEvent): void {
|
|
1402
|
+
if (this.treeMapTooltipModule) {
|
|
1403
|
+
this.treeMapTooltipModule.removeTooltip();
|
|
1404
|
+
}
|
|
1405
|
+
if (this.treeMapLegendModule) {
|
|
1406
|
+
this.treeMapLegendModule.removeInteractivePointer();
|
|
1407
|
+
}
|
|
1408
|
+
removeClassNames(document.getElementsByClassName('treeMapHighLight'), 'treeMapHighLight', this);
|
|
1409
|
+
if (this.treeMapHighlightModule) {
|
|
1410
|
+
removeShape(this.treeMapHighlightModule.shapeHighlightCollection, 'highlight');
|
|
1411
|
+
this.treeMapHighlightModule.highLightId = '';
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1415
|
+
/**
|
|
1416
|
+
* This method is used to select or remove the selection of treemap item based on the provided selection settings.
|
|
1417
|
+
*/
|
|
1418
|
+
public selectItem(levelOrder: string[], isSelected ?: boolean): void {
|
|
1419
|
+
if (isNullOrUndefined(isSelected)) {
|
|
1420
|
+
isSelected = true;
|
|
1421
|
+
}
|
|
1422
|
+
let levelOrderName: string = '';
|
|
1423
|
+
for (let i: number = 0; i < levelOrder.length; i++) {
|
|
1424
|
+
if (i !== levelOrder.length - 1) {
|
|
1425
|
+
levelOrderName += levelOrder[i] + '#';
|
|
1426
|
+
} else {
|
|
1427
|
+
levelOrderName += levelOrder[i];
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
if (this.treeMapSelectionModule && this.selectionSettings.enable) {
|
|
1431
|
+
this.treeMapSelectionModule.selectTreemapItem(levelOrderName, isSelected);
|
|
1432
|
+
}
|
|
1433
|
+
}
|
|
1434
|
+
|
|
1435
|
+
|
|
1436
|
+
/**
|
|
1437
|
+
* To provide the array of modules needed for maps rendering
|
|
1438
|
+
*
|
|
1439
|
+
* @returns {ModuleDeclaration[]} Returns the modules
|
|
1440
|
+
* @private
|
|
1441
|
+
*/
|
|
1442
|
+
public requiredModules(): ModuleDeclaration[] {
|
|
1443
|
+
const modules: ModuleDeclaration[] = [];
|
|
1444
|
+
if (this.tooltipSettings.visible) {
|
|
1445
|
+
modules.push({
|
|
1446
|
+
member: 'treeMapTooltip',
|
|
1447
|
+
args: [this]
|
|
1448
|
+
});
|
|
1449
|
+
}
|
|
1450
|
+
if (this.highlightSettings.enable) {
|
|
1451
|
+
modules.push({
|
|
1452
|
+
member: 'treeMapHighlight',
|
|
1453
|
+
args: [this]
|
|
1454
|
+
});
|
|
1455
|
+
}
|
|
1456
|
+
if (this.selectionSettings.enable) {
|
|
1457
|
+
modules.push({
|
|
1458
|
+
member: 'treeMapSelection',
|
|
1459
|
+
args: [this]
|
|
1460
|
+
});
|
|
1461
|
+
}
|
|
1462
|
+
if (this.legendSettings.visible) {
|
|
1463
|
+
modules.push({
|
|
1464
|
+
member: 'treeMapLegend',
|
|
1465
|
+
args: [this]
|
|
1466
|
+
});
|
|
1467
|
+
}
|
|
1468
|
+
if (this.allowPrint) {
|
|
1469
|
+
modules.push({
|
|
1470
|
+
member: 'Print',
|
|
1471
|
+
args: [this, Print]
|
|
1472
|
+
});
|
|
1473
|
+
}
|
|
1474
|
+
if (this.allowImageExport) {
|
|
1475
|
+
modules.push({
|
|
1476
|
+
member: 'ImageExport',
|
|
1477
|
+
args: [this, ImageExport]
|
|
1478
|
+
});
|
|
1479
|
+
}
|
|
1480
|
+
if (this.allowPdfExport) {
|
|
1481
|
+
modules.push({
|
|
1482
|
+
member: 'PdfExport',
|
|
1483
|
+
args: [this, PdfExport]
|
|
1484
|
+
});
|
|
1485
|
+
}
|
|
1486
|
+
return modules;
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1489
|
+
/**
|
|
1490
|
+
* Called internally if any of the property value changed.
|
|
1491
|
+
*
|
|
1492
|
+
* @param {TreeMapModel} newProp - Specifies the new property
|
|
1493
|
+
* @param {TreeMapModel} oldProp - Specifies the old property
|
|
1494
|
+
* @returns {void}
|
|
1495
|
+
* @private
|
|
1496
|
+
*/
|
|
1497
|
+
public onPropertyChanged(newProp: TreeMapModel, oldProp: TreeMapModel): void {
|
|
1498
|
+
let render: boolean = false;
|
|
1499
|
+
for (const prop of Object.keys(newProp)) {
|
|
1500
|
+
switch (prop) {
|
|
1501
|
+
case 'background':
|
|
1502
|
+
this.renderBorder();
|
|
1503
|
+
break;
|
|
1504
|
+
case 'height':
|
|
1505
|
+
case 'width':
|
|
1506
|
+
case 'layoutType':
|
|
1507
|
+
case 'levels':
|
|
1508
|
+
case 'drillDownView':
|
|
1509
|
+
case 'renderDirection':
|
|
1510
|
+
case 'leafItemSettings':
|
|
1511
|
+
case 'legendSettings':
|
|
1512
|
+
case 'dataSource':
|
|
1513
|
+
render = true;
|
|
1514
|
+
break;
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1517
|
+
if (render) {
|
|
1518
|
+
this.createSvg();
|
|
1519
|
+
this.renderElements();
|
|
1520
|
+
}
|
|
1521
|
+
}
|
|
1522
|
+
|
|
1523
|
+
/**
|
|
1524
|
+
* Gets component name.
|
|
1525
|
+
*/
|
|
1526
|
+
public getModuleName(): string {
|
|
1527
|
+
return 'treemap';
|
|
1528
|
+
}
|
|
1529
|
+
|
|
1530
|
+
/**
|
|
1531
|
+
* This method is used to dispose the treemap component.
|
|
1532
|
+
*/
|
|
1533
|
+
public destroy(): void {
|
|
1534
|
+
this.unWireEVents();
|
|
1535
|
+
this.drilledItems = [];
|
|
1536
|
+
this.levelSelection = [];
|
|
1537
|
+
this.legendId = [];
|
|
1538
|
+
this.removeSvg();
|
|
1539
|
+
super.destroy();
|
|
1540
|
+
}
|
|
1541
|
+
|
|
1542
|
+
private removeSvg(): void {
|
|
1543
|
+
removeElement(this.element.id + '_Secondary_Element');
|
|
1544
|
+
if (this.svgObject) {
|
|
1545
|
+
while (this.svgObject.childNodes.length > 0) {
|
|
1546
|
+
this.svgObject.removeChild(this.svgObject.firstChild);
|
|
1547
|
+
}
|
|
1548
|
+
if (!this.svgObject.hasChildNodes() && this.svgObject.parentNode) {
|
|
1549
|
+
remove(this.svgObject);
|
|
1550
|
+
}
|
|
1551
|
+
}
|
|
1552
|
+
}
|
|
1553
|
+
|
|
1554
|
+
/**
|
|
1555
|
+
* Get the properties to be maintained in the persisted state.
|
|
1556
|
+
*
|
|
1557
|
+
* @returns {string} - Returns the string value.
|
|
1558
|
+
* @private
|
|
1559
|
+
*/
|
|
1560
|
+
public getPersistData(): string {
|
|
1561
|
+
return '';
|
|
1562
|
+
}
|
|
1563
|
+
}
|
|
1564
|
+
|
|
1565
|
+
/**
|
|
1566
|
+
* @private
|
|
1567
|
+
*/
|
|
1568
|
+
export class LevelsData {
|
|
1569
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1570
|
+
public static levelsData : any[];
|
|
1571
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1572
|
+
public static defaultLevelsData : any[];
|
|
1573
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
1574
|
+
public static hierarchyData : any[];
|
|
1575
|
+
}
|